feat: add collect_for_each flow type to bot-config UI
- Dropdown option '🌧 Registro por ítem' in both PHP-rendered cards and the addFlowCard() JS template - Fields panel: endpoint lista, endpoint upload, campo ID, campo nombre, encabezado, pregunta por ítem, mensaje de éxito - flowTabChange() now shows/hides ftg-foreach panel - Save handler in index.php parses all flow_fe_* POST fields and builds the collect_for_each config object Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
b45f0fbe51
commit
fb61a6e027
@@ -2917,15 +2917,24 @@ HTML;
|
||||
$showEp = ($ft === 'function' && $fFn === 'api_report')
|
||||
? 'display:flex;flex-direction:column;gap:8px;margin-top:8px'
|
||||
: 'display:none';
|
||||
$showCollect = $ft === 'collect_input'
|
||||
? 'display:flex;flex-direction:column;gap:8px'
|
||||
: 'display:none';
|
||||
$showDynList = $ft === 'dynamic_list'
|
||||
? 'display:flex;flex-direction:column;gap:8px'
|
||||
: 'display:none';
|
||||
$showSubmit = $ft === 'submit_form'
|
||||
? 'display:flex;flex-direction:column;gap:8px'
|
||||
: 'display:none';
|
||||
$showCollect = $ft === 'collect_input' ? 'display:flex;flex-direction:column;gap:8px' : 'display:none';
|
||||
$showDynList = $ft === 'dynamic_list' ? 'display:flex;flex-direction:column;gap:8px' : 'display:none';
|
||||
$showSubmit = $ft === 'submit_form' ? 'display:flex;flex-direction:column;gap:8px' : 'display:none';
|
||||
$showForEach = $ft === 'collect_for_each' ? 'display:flex;flex-direction:column;gap:8px' : 'display:none';
|
||||
|
||||
$feEpSelHtml = '<option value="">— Selecciona endpoint lista —</option>';
|
||||
foreach ($companyEndpoints as $ep) {
|
||||
$sel = $srcEp === self::h($ep['endpoint_key']) ? ' selected' : '';
|
||||
$feEpSelHtml .= '<option value="' . self::h($ep['endpoint_key']) . '"' . $sel . '>' . $epLabel($ep) . '</option>';
|
||||
}
|
||||
$feUpEpSelHtml = '<option value="">— Selecciona endpoint upload —</option>';
|
||||
$feUpEpKey = self::h($flow['endpoint_key'] ?? '');
|
||||
foreach ($companyEndpoints as $ep) {
|
||||
$sel = $feUpEpKey === self::h($ep['endpoint_key']) ? ' selected' : '';
|
||||
$feUpEpSelHtml .= '<option value="' . self::h($ep['endpoint_key']) . '"' . $sel . '>' . $epLabel($ep) . '</option>';
|
||||
}
|
||||
$feQuestion = self::h($flow['question'] ?? '');
|
||||
$feSuccessText = self::h($flow['success_text'] ?? '');
|
||||
|
||||
$fnOpts = '';
|
||||
foreach (['goodbye' => '↩️ Salir (goodbye)', 'api_report' => '📄 Descargar informe', 'forward_to_ai' => '🤖 Escalar a IA', 'forward_to_agent' => '👤 Escalar a agente'] as $fv => $fl) {
|
||||
@@ -2956,9 +2965,10 @@ HTML;
|
||||
<option value=\"function\"" . ($ft==='function'?' selected':'') . ">⚡ Función especial</option>
|
||||
</optgroup>
|
||||
<optgroup label=\"Formulario\">
|
||||
<option value=\"collect_input\"" . ($ft==='collect_input'?' selected':'') . ">✏️ Pedir dato</option>
|
||||
<option value=\"dynamic_list\"" . ($ft==='dynamic_list'?' selected':'') . ">📋 Lista dinámica</option>
|
||||
<option value=\"submit_form\"" . ($ft==='submit_form'?' selected':'') . ">🚀 Enviar formulario</option>
|
||||
<option value=\"collect_input\"" . ($ft==='collect_input' ?' selected':'') . ">✏️ Pedir dato</option>
|
||||
<option value=\"dynamic_list\"" . ($ft==='dynamic_list' ?' selected':'') . ">📋 Lista dinámica</option>
|
||||
<option value=\"collect_for_each\"" . ($ft==='collect_for_each'?' selected':'') . ">🌧 Registro por ítem</option>
|
||||
<option value=\"submit_form\"" . ($ft==='submit_form' ?' selected':'') . ">🚀 Enviar formulario</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
@@ -3028,6 +3038,21 @@ HTML;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- collect_for_each -->
|
||||
<div class=\"ftg-foreach\" style=\"{$showForEach}\">
|
||||
<div style=\"display:grid;grid-template-columns:1fr 1fr;gap:8px\">
|
||||
<div><label>Endpoint lista (fincas)</label><select name=\"flow_fe_src_ep[]\">{$feEpSelHtml}</select></div>
|
||||
<div><label>Endpoint upload (POST)</label><select name=\"flow_fe_up_ep[]\">{$feUpEpSelHtml}</select></div>
|
||||
</div>
|
||||
<div style=\"display:grid;grid-template-columns:1fr 1fr;gap:8px\">
|
||||
<div><label>Campo ID del ítem</label><input type=\"text\" name=\"flow_fe_val_field[]\" value=\"{$valF}\" placeholder=\"id\"></div>
|
||||
<div><label>Campo nombre del ítem</label><input type=\"text\" name=\"flow_fe_lbl_field[]\" value=\"{$lblF}\" placeholder=\"nombre\"></div>
|
||||
</div>
|
||||
<div><label>Encabezado</label><input type=\"text\" name=\"flow_fe_header[]\" value=\"{$header}\" placeholder=\"🌧 Pluviometría\"></div>
|
||||
<div><label>Pregunta por ítem</label><input type=\"text\" name=\"flow_fe_question[]\" value=\"{$feQuestion}\" placeholder=\"¿Cuál es el valor? (mm)\"></div>
|
||||
<div><label>Mensaje de éxito</label><input type=\"text\" name=\"flow_fe_success[]\" value=\"{$feSuccessText}\" placeholder=\"✅ Datos registrados correctamente.\"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>";
|
||||
@@ -3284,12 +3309,13 @@ function flowTabChange(sel) {
|
||||
const v = sel.value;
|
||||
// flex sections need display:flex; block sections use '' (default block)
|
||||
const sections = {
|
||||
'ftg-text': {show: v==='text', flex: false},
|
||||
'ftg-menu': {show: v==='menu', flex: false},
|
||||
'ftg-fn': {show: v==='function', flex: false},
|
||||
'ftg-collect': {show: v==='collect_input', flex: true},
|
||||
'ftg-dynlist': {show: v==='dynamic_list', flex: true},
|
||||
'ftg-submit': {show: v==='submit_form', flex: true},
|
||||
'ftg-text': {show: v==='text', flex: false},
|
||||
'ftg-menu': {show: v==='menu', flex: false},
|
||||
'ftg-fn': {show: v==='function', flex: false},
|
||||
'ftg-collect': {show: v==='collect_input', flex: true},
|
||||
'ftg-dynlist': {show: v==='dynamic_list', flex: true},
|
||||
'ftg-submit': {show: v==='submit_form', flex: true},
|
||||
'ftg-foreach': {show: v==='collect_for_each', flex: true},
|
||||
};
|
||||
for (const [cls, cfg] of Object.entries(sections)) {
|
||||
const el = card.querySelector('.' + cls);
|
||||
@@ -3340,6 +3366,7 @@ function addFlowCard() {
|
||||
' <optgroup label="Formulario">' +
|
||||
' <option value="collect_input">✏️ Pedir dato</option>' +
|
||||
' <option value="dynamic_list">📋 Lista dinámica</option>' +
|
||||
' <option value="collect_for_each">🌧 Registro por ítem</option>' +
|
||||
' <option value="submit_form">🚀 Enviar formulario</option>' +
|
||||
' </optgroup>' +
|
||||
' </select>' +
|
||||
@@ -3397,6 +3424,19 @@ function addFlowCard() {
|
||||
' <div><label>Mensaje</label><input type="text" name="flow_sf_caption[]" placeholder="Aquí tienes el informe."></div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' <div class="ftg-foreach" style="display:none;flex-direction:column;gap:8px">' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Endpoint lista</label><select name="flow_fe_src_ep[]">' + epOpts + '</select></div>' +
|
||||
' <div><label>Endpoint upload (POST)</label><select name="flow_fe_up_ep[]">' + epOpts + '</select></div>' +
|
||||
' </div>' +
|
||||
' <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">' +
|
||||
' <div><label>Campo ID</label><input type="text" name="flow_fe_val_field[]" placeholder="id"></div>' +
|
||||
' <div><label>Campo nombre</label><input type="text" name="flow_fe_lbl_field[]" placeholder="nombre"></div>' +
|
||||
' </div>' +
|
||||
' <div><label>Encabezado</label><input type="text" name="flow_fe_header[]" placeholder="🌧 Pluviometría"></div>' +
|
||||
' <div><label>Pregunta por ítem</label><input type="text" name="flow_fe_question[]" placeholder="¿Cuál es el valor? (mm)"></div>' +
|
||||
' <div><label>Mensaje de éxito</label><input type="text" name="flow_fe_success[]" placeholder="✅ Datos registrados."></div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
'</div>'
|
||||
|
||||
@@ -414,6 +414,13 @@ $routes = [
|
||||
$flowSfGroups = $_POST['flow_sf_meta_group']?? [];
|
||||
$flowSfFnames = $_POST['flow_sf_filename'] ?? [];
|
||||
$flowSfCaps = $_POST['flow_sf_caption'] ?? [];
|
||||
$flowFeSrcEps = $_POST['flow_fe_src_ep'] ?? [];
|
||||
$flowFeUpEps = $_POST['flow_fe_up_ep'] ?? [];
|
||||
$flowFeValFlds = $_POST['flow_fe_val_field'] ?? [];
|
||||
$flowFeLblFlds = $_POST['flow_fe_lbl_field'] ?? [];
|
||||
$flowFeHeaders = $_POST['flow_fe_header'] ?? [];
|
||||
$flowFeQs = $_POST['flow_fe_question'] ?? [];
|
||||
$flowFeSucTxts = $_POST['flow_fe_success'] ?? [];
|
||||
|
||||
$flows = [];
|
||||
foreach ($flowKeys as $i => $fk) {
|
||||
@@ -465,6 +472,15 @@ $routes = [
|
||||
$f['meta_group'] = trim($flowSfGroups[$i] ?? '');
|
||||
$f['filename'] = trim($flowSfFnames[$i] ?? '');
|
||||
$f['caption'] = trim($flowSfCaps[$i] ?? '');
|
||||
|
||||
} elseif ($ftype === 'collect_for_each') {
|
||||
$f['source_endpoint_key'] = trim($flowFeSrcEps[$i] ?? '');
|
||||
$f['endpoint_key'] = trim($flowFeUpEps[$i] ?? '');
|
||||
$f['value_field'] = trim($flowFeValFlds[$i] ?? 'id');
|
||||
$f['label_field'] = trim($flowFeLblFlds[$i] ?? 'nombre');
|
||||
$f['header'] = trim($flowFeHeaders[$i] ?? '');
|
||||
$f['question'] = trim($flowFeQs[$i] ?? '');
|
||||
$f['success_text'] = trim($flowFeSucTxts[$i] ?? '');
|
||||
}
|
||||
|
||||
$flows[$fk] = $f;
|
||||
|
||||
Reference in New Issue
Block a user