fix: avoid PHP interpolating JS template literals in addFlowCard heredoc
Replace all backtick template literals inside addFlowCard (which lives
inside a PHP heredoc) with plain string concatenation. PHP was evaluating
${k}, ${Date.now()}, ${menuOpts}, etc. as PHP variable expressions,
emitting deprecation warnings inside the <script> block and corrupting
the JavaScript — causing all tab buttons on bot-config to stop responding.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
1116b8ece9
commit
845dd08a3a
@@ -3123,92 +3123,94 @@ function addFlowCard() {
|
||||
|
||||
const menus = CONFIG?.menus || {};
|
||||
let menuOpts = '<option value="">— Selecciona menú —</option>';
|
||||
for (const k of Object.keys(menus)) menuOpts += `<option value="${k}">📑 ${k}</option>`;
|
||||
for (const k of Object.keys(menus)) menuOpts += '<option value="' + k + '">📑 ' + k + '</option>';
|
||||
|
||||
const eps = ENDPOINTS || {};
|
||||
let epOpts = '<option value="">— Ninguno —</option>';
|
||||
for (const [k, ep] of Object.entries(eps)) epOpts += `<option value="${k}">${ep.name || k}</option>`;
|
||||
for (const [k, ep] of Object.entries(eps)) epOpts += '<option value="' + k + '">' + (ep.name || k) + '</option>';
|
||||
|
||||
const flows = CONFIG?.flows || {};
|
||||
let nnOpts = '<option value="">— Ninguno —</option>';
|
||||
for (const k of Object.keys(flows)) nnOpts += `<option value="${k}">${k}</option>`;
|
||||
for (const k of Object.keys(flows)) nnOpts += '<option value="' + k + '">' + k + '</option>';
|
||||
|
||||
container.insertAdjacentHTML('beforeend', `
|
||||
<div class="item-card" id="flow-card-${Date.now()}">
|
||||
<div class="item-head">
|
||||
<span>ID: <input type="text" name="flow_key[]" value="" style="border:none;background:transparent;font-weight:700;color:#0b3d91;width:180px;font-size:13px" placeholder="nuevo_flujo"></span>
|
||||
<button type="button" class="del" onclick="this.closest('.item-card').remove()">✕</button>
|
||||
</div>
|
||||
<div class="form-row" style="align-items:flex-start;gap:10px">
|
||||
<div class="form-group" style="min-width:200px">
|
||||
<label>¿Qué hace?</label>
|
||||
<select name="flow_type[]" onchange="flowTabChange(this)">
|
||||
<optgroup label="Respuesta"><option value="text" selected>💬 Texto fijo</option></optgroup>
|
||||
<optgroup label="Navegar"><option value="menu">📑 Mostrar menú</option></optgroup>
|
||||
<optgroup label="Acción directa"><option value="function">⚡ Función especial</option></optgroup>
|
||||
<optgroup label="Formulario">
|
||||
<option value="collect_input">✏️ Pedir dato</option>
|
||||
<option value="dynamic_list">📋 Lista dinámica</option>
|
||||
<option value="submit_form">🚀 Enviar formulario</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div style="flex:1;display:flex;flex-direction:column;gap:10px">
|
||||
<div class="ftg-text"><textarea name="flow_message[]" rows="2" placeholder="Texto que recibirá el usuario"></textarea></div>
|
||||
<div class="ftg-menu" style="display:none"><label>Menú a mostrar</label><select name="flow_menu[]">${menuOpts}</select></div>
|
||||
<div class="ftg-fn" style="display:none">
|
||||
<label>Función</label>
|
||||
<select name="flow_function[]" onchange="flowFnTabChange(this)">
|
||||
<option value="goodbye">↩️ Salir (goodbye)</option>
|
||||
<option value="api_report">📄 Descargar informe</option>
|
||||
<option value="forward_to_ai">🤖 Escalar a IA</option>
|
||||
<option value="forward_to_agent">👤 Escalar a agente</option>
|
||||
</select>
|
||||
<div class="ftg-ep" style="display:none;flex-direction:column;gap:8px;margin-top:8px">
|
||||
<div><label>Endpoint</label><select name="flow_ep_key[]">${epOpts}</select></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
|
||||
<div><label>Periodo</label><select name="flow_date_mode[]"><option value="">Sin fecha</option><option value="today">Hoy</option><option value="last_30">Últimos 30 días</option></select></div>
|
||||
<div><label>Nombre archivo</label><input type="text" name="flow_filename[]" placeholder="reporte.pdf"></div>
|
||||
</div>
|
||||
<div><label>Mensaje al enviar</label><input type="text" name="flow_caption[]" placeholder="Aquí tienes el informe."></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ftg-collect" style="display:none;flex-direction:column;gap:8px">
|
||||
<div><label>Pregunta al usuario</label><input type="text" name="flow_prompt[]" placeholder="¿Desde qué fecha? (YYYY-MM-DD)"></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
|
||||
<div><label>Grupo formulario</label><input type="text" name="flow_meta_group[]" placeholder="form_prod"></div>
|
||||
<div><label>Campo</label><input type="text" name="flow_meta_key[]" placeholder="desde"></div>
|
||||
</div>
|
||||
<div><label>Flujo siguiente</label><select name="flow_next_node[]">${nnOpts}</select></div>
|
||||
</div>
|
||||
<div class="ftg-dynlist" style="display:none;flex-direction:column;gap:8px">
|
||||
<div><label>Endpoint (lista)</label><select name="flow_dl_ep[]">${epOpts}</select></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
|
||||
<div><label>Campo ID</label><input type="text" name="flow_val_field[]" placeholder="id"></div>
|
||||
<div><label>Campo etiqueta</label><input type="text" name="flow_lbl_field[]" placeholder="nombre"></div>
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
|
||||
<div><label>Encabezado</label><input type="text" name="flow_header[]" placeholder="Selecciona..."></div>
|
||||
<div><label>Título sección</label><input type="text" name="flow_sec_title[]" placeholder="Opciones"></div>
|
||||
</div>
|
||||
<div><label>Cuerpo</label><input type="text" name="flow_body[]" placeholder="¿Cuál deseas?"></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
|
||||
<div><label>Grupo formulario</label><input type="text" name="flow_dl_meta_group[]" placeholder="form_prod"></div>
|
||||
<div><label>Campo</label><input type="text" name="flow_dl_meta_key[]" placeholder="finca_id"></div>
|
||||
</div>
|
||||
<div><label>Flujo siguiente</label><select name="flow_dl_next[]">${nnOpts}</select></div>
|
||||
</div>
|
||||
<div class="ftg-submit" style="display:none;flex-direction:column;gap:8px">
|
||||
<div><label>Endpoint destino</label><select name="flow_sf_ep[]">${epOpts}</select></div>
|
||||
<div><label>Grupo formulario</label><input type="text" name="flow_sf_meta_group[]" placeholder="form_prod"></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
|
||||
<div><label>Nombre archivo</label><input type="text" name="flow_sf_filename[]" placeholder="reporte.pdf"></div>
|
||||
<div><label>Mensaje</label><input type="text" name="flow_sf_caption[]" placeholder="Aquí tienes el informe."></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
const cardId = 'flow-card-' + Date.now();
|
||||
container.insertAdjacentHTML('beforeend',
|
||||
'<div class="item-card" id="' + cardId + '">' +
|
||||
' <div class="item-head">' +
|
||||
' <span>ID: <input type="text" name="flow_key[]" value="" style="border:none;background:transparent;font-weight:700;color:#0b3d91;width:180px;font-size:13px" placeholder="nuevo_flujo"></span>' +
|
||||
' <button type="button" class="del" onclick="this.closest(\'.item-card\').remove()">✕</button>' +
|
||||
' </div>' +
|
||||
' <div class="form-row" style="align-items:flex-start;gap:10px">' +
|
||||
' <div class="form-group" style="min-width:200px">' +
|
||||
' <label>¿Qué hace?</label>' +
|
||||
' <select name="flow_type[]" onchange="flowTabChange(this)">' +
|
||||
' <optgroup label="Respuesta"><option value="text" selected>💬 Texto fijo</option></optgroup>' +
|
||||
' <optgroup label="Navegar"><option value="menu">📑 Mostrar menú</option></optgroup>' +
|
||||
' <optgroup label="Acción directa"><option value="function">⚡ Función especial</option></optgroup>' +
|
||||
' <optgroup label="Formulario">' +
|
||||
' <option value="collect_input">✏️ Pedir dato</option>' +
|
||||
' <option value="dynamic_list">📋 Lista dinámica</option>' +
|
||||
' <option value="submit_form">🚀 Enviar formulario</option>' +
|
||||
' </optgroup>' +
|
||||
' </select>' +
|
||||
' </div>' +
|
||||
' <div style="flex:1;display:flex;flex-direction:column;gap:10px">' +
|
||||
' <div class="ftg-text"><textarea name="flow_message[]" rows="2" placeholder="Texto que recibirá el usuario"></textarea></div>' +
|
||||
' <div class="ftg-menu" style="display:none"><label>Menú a mostrar</label><select name="flow_menu[]">' + menuOpts + '</select></div>' +
|
||||
' <div class="ftg-fn" style="display:none">' +
|
||||
' <label>Función</label>' +
|
||||
' <select name="flow_function[]" onchange="flowFnTabChange(this)">' +
|
||||
' <option value="goodbye">↩️ Salir (goodbye)</option>' +
|
||||
' <option value="api_report">📄 Descargar informe</option>' +
|
||||
' <option value="forward_to_ai">🤖 Escalar a IA</option>' +
|
||||
' <option value="forward_to_agent">👤 Escalar a agente</option>' +
|
||||
' </select>' +
|
||||
' <div class="ftg-ep" style="display:none;flex-direction:column;gap:8px;margin-top:8px">' +
|
||||
' <div><label>Endpoint</label><select name="flow_ep_key[]">' + epOpts + '</select></div>' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Periodo</label><select name="flow_date_mode[]"><option value="">Sin fecha</option><option value="today">Hoy</option><option value="last_30">Últimos 30 días</option></select></div>' +
|
||||
' <div><label>Nombre archivo</label><input type="text" name="flow_filename[]" placeholder="reporte.pdf"></div>' +
|
||||
' </div>' +
|
||||
' <div><label>Mensaje al enviar</label><input type="text" name="flow_caption[]" placeholder="Aquí tienes el informe."></div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' <div class="ftg-collect" style="display:none;flex-direction:column;gap:8px">' +
|
||||
' <div><label>Pregunta al usuario</label><input type="text" name="flow_prompt[]" placeholder="¿Desde qué fecha? (YYYY-MM-DD)"></div>' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Grupo formulario</label><input type="text" name="flow_meta_group[]" placeholder="form_prod"></div>' +
|
||||
' <div><label>Campo</label><input type="text" name="flow_meta_key[]" placeholder="desde"></div>' +
|
||||
' </div>' +
|
||||
' <div><label>Flujo siguiente</label><select name="flow_next_node[]">' + nnOpts + '</select></div>' +
|
||||
' </div>' +
|
||||
' <div class="ftg-dynlist" style="display:none;flex-direction:column;gap:8px">' +
|
||||
' <div><label>Endpoint (lista)</label><select name="flow_dl_ep[]">' + epOpts + '</select></div>' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Campo ID</label><input type="text" name="flow_val_field[]" placeholder="id"></div>' +
|
||||
' <div><label>Campo etiqueta</label><input type="text" name="flow_lbl_field[]" placeholder="nombre"></div>' +
|
||||
' </div>' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Encabezado</label><input type="text" name="flow_header[]" placeholder="Selecciona..."></div>' +
|
||||
' <div><label>Título sección</label><input type="text" name="flow_sec_title[]" placeholder="Opciones"></div>' +
|
||||
' </div>' +
|
||||
' <div><label>Cuerpo</label><input type="text" name="flow_body[]" placeholder="¿Cuál deseas?"></div>' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Grupo formulario</label><input type="text" name="flow_dl_meta_group[]" placeholder="form_prod"></div>' +
|
||||
' <div><label>Campo</label><input type="text" name="flow_dl_meta_key[]" placeholder="finca_id"></div>' +
|
||||
' </div>' +
|
||||
' <div><label>Flujo siguiente</label><select name="flow_dl_next[]">' + nnOpts + '</select></div>' +
|
||||
' </div>' +
|
||||
' <div class="ftg-submit" style="display:none;flex-direction:column;gap:8px">' +
|
||||
' <div><label>Endpoint destino</label><select name="flow_sf_ep[]">' + epOpts + '</select></div>' +
|
||||
' <div><label>Grupo formulario</label><input type="text" name="flow_sf_meta_group[]" placeholder="form_prod"></div>' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Nombre archivo</label><input type="text" name="flow_sf_filename[]" placeholder="reporte.pdf"></div>' +
|
||||
' <div><label>Mensaje</label><input type="text" name="flow_sf_caption[]" placeholder="Aquí tienes el informe."></div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
'</div>'
|
||||
);
|
||||
container.lastElementChild.scrollIntoView({behavior:'smooth'});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user