fix(studio): los campos Cliente y Plan no aparecían al crear un tenant
/app/api/clientes/select devuelve el array pelado y /app/umind-planes/list
lo envuelve en {items}. El código leía solo .registros/.items, así que con
el array quedaba vacío — y el bloque estaba detrás de v-if="clientes.length",
o sea que Cliente y Plan simplemente no se veían y no había forma de
asignarlos.
- lista() acepta las dos formas (verificado contra ambas y contra
vacío/null/undefined).
- Se cargan con allSettled: que falle uno ya no vacía el otro.
- El bloque se muestra siempre para el staff, y cada select dice a dónde ir
si su lista está vacía. Antes un fallo de red se veía exactamente igual
que "no hay nada configurado", que es lo que enmascaró este bug.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
693ff608b1
commit
115f1675ad
@@ -37,21 +37,31 @@ async function cargar() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clientes y planes solo los necesita el staff para asignarlos; si el endpoint
|
// Los endpoints del panel no comparten una forma de respuesta: el de clientes
|
||||||
// no está disponible (portal del cliente) el formulario sigue funcionando.
|
// devuelve el array pelado y el de planes lo envuelve en {items}. Aceptar las
|
||||||
|
// dos evita que un select quede vacío sin que nadie se entere.
|
||||||
|
function lista(r) {
|
||||||
|
if (Array.isArray(r)) return r
|
||||||
|
return r?.items || r?.registros || []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clientes y planes solo los necesita el staff para asignarlos; en el portal
|
||||||
|
// del cliente esos endpoints no se alcanzan y el formulario no los muestra.
|
||||||
|
// Se cargan por separado a propósito: que falle uno no debe vaciar el otro.
|
||||||
async function cargarAsignables() {
|
async function cargarAsignables() {
|
||||||
if (contexto.esPortal) return // endpoints de staff: el cliente no los alcanza
|
if (contexto.esPortal) return
|
||||||
try {
|
const [c, p] = await Promise.allSettled([
|
||||||
const [c, p] = await Promise.all([
|
|
||||||
api.get('/app/api/clientes/select'),
|
api.get('/app/api/clientes/select'),
|
||||||
api.get('/app/umind-planes/list'),
|
api.get('/app/umind-planes/list'),
|
||||||
])
|
])
|
||||||
clientes.value = c.registros || c.items || []
|
clientes.value = c.status === 'fulfilled' ? lista(c.value) : []
|
||||||
planes.value = p.items || []
|
planes.value = p.status === 'fulfilled' ? lista(p.value) : []
|
||||||
} catch {
|
// Sin esto un fallo se veía igual que "no hay nada configurado", que es
|
||||||
clientes.value = []
|
// justo lo que hizo que los campos Cliente y Plan no aparecieran.
|
||||||
planes.value = []
|
const fallos = []
|
||||||
}
|
if (c.status === 'rejected') fallos.push('clientes')
|
||||||
|
if (p.status === 'rejected') fallos.push('planes')
|
||||||
|
if (fallos.length) error.value = `No se pudo cargar la lista de ${fallos.join(' ni ')}.`
|
||||||
}
|
}
|
||||||
|
|
||||||
function nuevoTenant() {
|
function nuevoTenant() {
|
||||||
@@ -202,7 +212,7 @@ onMounted(() => {
|
|||||||
class="input"
|
class="input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="clientes.length" class="grid grid-cols-2 gap-3">
|
<div v-if="!contexto.esPortal" class="grid grid-cols-2 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label class="label">Cliente</label>
|
<label class="label">Cliente</label>
|
||||||
<select
|
<select
|
||||||
@@ -212,7 +222,9 @@ onMounted(() => {
|
|||||||
<option :value="null">— sin asignar —</option>
|
<option :value="null">— sin asignar —</option>
|
||||||
<option v-for="c in clientes" :key="c.ID" :value="c.ID">{{ c.nombre }}</option>
|
<option v-for="c in clientes" :key="c.ID" :value="c.ID">{{ c.nombre }}</option>
|
||||||
</select>
|
</select>
|
||||||
<p class="text-[11px] text-tenue mt-1">Define quién ve este tenant desde el portal.</p>
|
<p class="text-[11px] text-tenue mt-1">
|
||||||
|
{{ clientes.length ? 'Define quién ve este tenant desde el portal.' : 'No hay clientes activos — creá uno en Clientes.' }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="label">Plan</label>
|
<label class="label">Plan</label>
|
||||||
@@ -225,7 +237,9 @@ onMounted(() => {
|
|||||||
{{ p.nombre }} ({{ p.max_agentes === 0 ? '∞' : p.max_agentes }} agentes)
|
{{ p.nombre }} ({{ p.max_agentes === 0 ? '∞' : p.max_agentes }} agentes)
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<p class="text-[11px] text-tenue mt-1">Límite de agentes y precios de consumo.</p>
|
<p class="text-[11px] text-tenue mt-1">
|
||||||
|
{{ planes.length ? 'Límite de agentes y precios de consumo.' : 'No hay planes — creá uno en uMind Planes.' }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label class="flex items-center gap-2 text-sm text-texto">
|
<label class="flex items-center gap-2 text-sm text-texto">
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>uMind Studio</title>
|
<title>uMind Studio</title>
|
||||||
<script type="module" crossorigin src="/orchestrator/assets/index-DP70_OF3.js"></script>
|
<script type="module" crossorigin src="/orchestrator/assets/index-D9xKBSe-.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/orchestrator/assets/index-CkF90HJJ.css">
|
<link rel="stylesheet" crossorigin href="/orchestrator/assets/index-CkF90HJJ.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-gray-50">
|
<body class="bg-gray-50">
|
||||||
|
|||||||
Reference in New Issue
Block a user