Diferencia entre revisiones de «MediaWiki:Common.js»

De Historia del Club Escuela de Piraguismo Aranjuez
Saltar a: navegación, buscar
 
(No se muestran 4 ediciones intermedias del mismo usuario)
Línea 1: Línea 1:
/* WIKICONSULTAS - Chat de consultas (Piragüismo en Aranjuez) */
+
/* ==========================================================
 +
  WIKICONSULTAS Chat de consultas
 +
  Especializado en: Piragüismo en Aranjuez
 +
  Ubicación: MediaWiki:Common.js
 +
  ========================================================== */
 +
 
 
(function () {
 
(function () {
 
   'use strict';
 
   'use strict';
  
   // === CONFIGURACIÓN ===
+
   // ================= CONFIGURACIÓN =================
   // Cambia esta URL por tu endpoint cuando lo tengas (puede ser Make, n8n, servidor propio, etc.)
+
   // Sustituye esta URL por el webhook de Make cuando lo tengas
 
   var WIKICONSULTAS_ENDPOINT = 'https://TU-DOMINIO.com/wikiconsultas';
 
   var WIKICONSULTAS_ENDPOINT = 'https://TU-DOMINIO.com/wikiconsultas';
  
  // Texto de dominio (para mantener el asistente “en su carril”)
 
 
   var SCOPE_NOTICE = 'Puedo ayudarte solo con consultas sobre el piragüismo en Aranjuez basándome en el contenido de esta wiki.';
 
   var SCOPE_NOTICE = 'Puedo ayudarte solo con consultas sobre el piragüismo en Aranjuez basándome en el contenido de esta wiki.';
  
 +
  // ================= ESTILOS =================
 
   function addStyles() {
 
   function addStyles() {
 
     mw.util.addCSS(`
 
     mw.util.addCSS(`
Línea 57: Línea 62:
 
         white-space:pre-wrap;
 
         white-space:pre-wrap;
 
       }
 
       }
      .wk-user .wk-bubble{ background:#fff; }
 
      .wk-bot  .wk-bubble{ background:#ffffff; }
 
 
       #wikiconsultas-foot{
 
       #wikiconsultas-foot{
 
         padding:10px; border-top:1px solid rgba(0,0,0,.10);
 
         padding:10px; border-top:1px solid rgba(0,0,0,.10);
Línea 72: Línea 75:
 
       }
 
       }
 
       #wikiconsultas-send:hover{ background:rgba(0,0,0,.04); }
 
       #wikiconsultas-send:hover{ background:rgba(0,0,0,.04); }
      .wk-muted{ color:#666; font-size:12px; margin-top:6px; }
 
 
     `);
 
     `);
 
   }
 
   }
  
 +
  // ================= DOM HELPERS =================
 
   function el(tag, attrs, children) {
 
   function el(tag, attrs, children) {
 
     var node = document.createElement(tag);
 
     var node = document.createElement(tag);
 
     if (attrs) Object.keys(attrs).forEach(function (k) { node.setAttribute(k, attrs[k]); });
 
     if (attrs) Object.keys(attrs).forEach(function (k) { node.setAttribute(k, attrs[k]); });
     (children || []).forEach(function (c) { node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c); });
+
     (children || []).forEach(function (c) {
 +
      node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c);
 +
    });
 
     return node;
 
     return node;
 
   }
 
   }
  
 
   function appendMsg(log, who, text) {
 
   function appendMsg(log, who, text) {
     var msg = el('div', { class: 'wk-msg ' + (who === 'user' ? 'wk-user' : 'wk-bot') }, [
+
     var msg = el('div', { class: 'wk-msg' }, [
 
       el('div', { class: 'wk-badge' }, [who === 'user' ? 'Tú' : 'WK']),
 
       el('div', { class: 'wk-badge' }, [who === 'user' ? 'Tú' : 'WK']),
 
       el('div', { class: 'wk-bubble' }, [text])
 
       el('div', { class: 'wk-bubble' }, [text])
Línea 101: Línea 106:
 
   }
 
   }
  
 +
  // ================= BACKEND =================
 
   async function askBackend(question) {
 
   async function askBackend(question) {
    // Si aún no has puesto endpoint real, devolvemos un aviso útil
 
 
     if (!WIKICONSULTAS_ENDPOINT || WIKICONSULTAS_ENDPOINT.indexOf('TU-DOMINIO.com') !== -1) {
 
     if (!WIKICONSULTAS_ENDPOINT || WIKICONSULTAS_ENDPOINT.indexOf('TU-DOMINIO.com') !== -1) {
       return "Aún no estoy conectado a un servicio de IA.\n\nPara activarme, configura WIKICONSULTAS_ENDPOINT en MediaWiki:Common.js con la URL de tu API.\n\nMientras tanto, dime qué página o sección te interesa y te indico dónde buscar dentro de la wiki.";
+
       return 'WIKICONSULTAS aún no está conectado a un servicio de IA.\n\nCuando tengas el webhook de Make, sustituye WIKICONSULTAS_ENDPOINT en MediaWiki:Common.js.';
 
     }
 
     }
  
 
     var payload = {
 
     var payload = {
       assistant: "WIKICONSULTAS",
+
       assistant: 'WIKICONSULTAS',
       scope: "Piragüismo en Aranjuez",
+
       scope: 'Piragüismo en Aranjuez',
 
       question: question,
 
       question: question,
 
       pageTitle: mw.config.get('wgTitle'),
 
       pageTitle: mw.config.get('wgTitle'),
 
       pageName: mw.config.get('wgPageName'),
 
       pageName: mw.config.get('wgPageName'),
 
       url: location.href,
 
       url: location.href,
       language: "es"
+
       language: 'es'
 
     };
 
     };
  
Línea 125: Línea 130:
 
     if (!res.ok) throw new Error('HTTP ' + res.status);
 
     if (!res.ok) throw new Error('HTTP ' + res.status);
 
     var data = await res.json();
 
     var data = await res.json();
 
+
     return data && data.answer ? data.answer : 'No se recibió respuesta válida del servicio.';
    // Espera { answer: "..." } (y opcionalmente suggested_pages)
 
     return (data && data.answer) ? data.answer : 'No he recibido respuesta válida del servicio.';
 
 
   }
 
   }
  
 +
  // ================= INIT =================
 
   function init() {
 
   function init() {
 
     if (document.getElementById('wikiconsultas-btn')) return;
 
     if (document.getElementById('wikiconsultas-btn')) return;
Línea 135: Línea 139:
 
     addStyles();
 
     addStyles();
  
 +
    // UI
 
     var btn = el('button', { id: 'wikiconsultas-btn', type: 'button', title: 'Abrir WIKICONSULTAS' }, ['WIKICONSULTAS']);
 
     var btn = el('button', { id: 'wikiconsultas-btn', type: 'button', title: 'Abrir WIKICONSULTAS' }, ['WIKICONSULTAS']);
 
     var overlay = el('div', { id: 'wikiconsultas-overlay', role: 'dialog', 'aria-modal': 'true' });
 
     var overlay = el('div', { id: 'wikiconsultas-overlay', role: 'dialog', 'aria-modal': 'true' });
Línea 145: Línea 150:
  
 
     var scope = el('div', { id: 'wikiconsultas-scope' }, [SCOPE_NOTICE]);
 
     var scope = el('div', { id: 'wikiconsultas-scope' }, [SCOPE_NOTICE]);
 
 
     var log = el('div', { id: 'wikiconsultas-log' });
 
     var log = el('div', { id: 'wikiconsultas-log' });
 
     var foot = el('div', { id: 'wikiconsultas-foot' });
 
     var foot = el('div', { id: 'wikiconsultas-foot' });
     var input = el('input', { id: 'wikiconsultas-input', type: 'text', placeholder: 'Escribe tu consulta… (ej: “¿qué etapas históricas recoge la wiki?”)' });
+
     var input = el('input', { id: 'wikiconsultas-input', type: 'text', placeholder: 'Escribe tu consulta…' });
 
     var send = el('button', { id: 'wikiconsultas-send', type: 'button' }, ['Enviar']);
 
     var send = el('button', { id: 'wikiconsultas-send', type: 'button' }, ['Enviar']);
  
Línea 164: Línea 168:
  
 
     // Mensaje inicial
 
     // Mensaje inicial
     appendMsg(log, 'bot', "Hola 👋 Soy WIKICONSULTAS.\nHazme preguntas sobre el piragüismo en Aranjuez basándome en el contenido de esta wiki.");
+
     appendMsg(log, 'bot', 'Hola 👋 Soy WIKICONSULTAS.\nHazme preguntas sobre el piragüismo en Aranjuez basándome en el contenido de esta wiki.');
  
     // Eventos
+
     // Eventos básicos
 
     btn.addEventListener('click', function () { openModal(overlay, input); });
 
     btn.addEventListener('click', function () { openModal(overlay, input); });
 
     document.getElementById('wikiconsultas-close').addEventListener('click', function () { closeModal(overlay); });
 
     document.getElementById('wikiconsultas-close').addEventListener('click', function () { closeModal(overlay); });
Línea 178: Línea 182:
 
       input.value = '';
 
       input.value = '';
 
       appendMsg(log, 'bot', 'Pensando…');
 
       appendMsg(log, 'bot', 'Pensando…');
 
      // Reemplaza el último “Pensando…” cuando llegue la respuesta
 
 
       var thinkingNode = log.lastChild;
 
       var thinkingNode = log.lastChild;
  
Línea 186: Línea 188:
 
         thinkingNode.querySelector('.wk-bubble').textContent = answer;
 
         thinkingNode.querySelector('.wk-bubble').textContent = answer;
 
       } catch (err) {
 
       } catch (err) {
         thinkingNode.querySelector('.wk-bubble').textContent =
+
         thinkingNode.querySelector('.wk-bubble').textContent = 'No he podido conectar con el servicio.\n\nDetalles: ' + (err && err.message ? err.message : String(err));
          "No he podido conectar con el servicio.\n\nDetalles: " + (err && err.message ? err.message : String(err));
 
 
       }
 
       }
 
     }
 
     }
Línea 197: Línea 198:
 
     });
 
     });
  
     // Permite abrirlo con #wikiconsultas en la URL
+
     // ==================================================
     if (location.hash === '#wikiconsultas') openModal(overlay, input);
+
    // APERTURA ROBUSTA DESDE LA PÁGINA
// Abrir/cerrar al cambiar el hash (para que el enlace funcione sin recargar)
+
    // 1) #wikiconsultas en la URL
window.addEventListener('hashchange', function () {
+
     // 2) Clic en cualquier enlace que contenga #wikiconsultas
  if (location.hash === '#wikiconsultas') {
+
    // 3) Clic en el “botón” de la página con id="wk-open"
    openModal(overlay, input);
+
    // ==================================================
 +
 
 +
    function openIfHash() {
 +
      if (location.hash === '#wikiconsultas') {
 +
        openModal(overlay, input);
 +
      }
 +
    }
 +
 
 +
    // Abre si carga con el hash
 +
    openIfHash();
 +
 
 +
    // Abre si cambia el hash
 +
    window.addEventListener('hashchange', openIfHash);
 +
 
 +
    // Captura clics (enlaces con #wikiconsultas)
 +
    document.addEventListener('click', function (e) {
 +
      var a = e.target && e.target.closest ? e.target.closest('a') : null;
 +
      if (!a) return;
 +
 
 +
      var href = a.getAttribute('href') || '';
 +
      if (href.indexOf('#wikiconsultas') !== -1) {
 +
        e.preventDefault();
 +
        e.stopPropagation();
 +
        try {
 +
          if (location.hash !== '#wikiconsultas') history.pushState(null, '', '#wikiconsultas');
 +
        } catch (_) {}
 +
        openModal(overlay, input);
 +
      }
 +
    }, true);
 +
 
 +
    // Clic directo en el “botón” embebido en la página principal
 +
    document.addEventListener('click', function (e) {
 +
      var node = e.target && e.target.closest ? e.target.closest('#wk-open') : null;
 +
      if (!node) return;
 +
      e.preventDefault();
 +
      e.stopPropagation();
 +
      try {
 +
        if (location.hash !== '#wikiconsultas') history.pushState(null, '', '#wikiconsultas');
 +
      } catch (_) {}
 +
      openModal(overlay, input);
 +
    }, true);
 
   }
 
   }
});
+
 
 +
  mw.loader.using(['mediawiki.util']).then(init);
 +
})();
 +
 
 +
/*
 +
PASOS TRAS PEGAR ESTE ARCHIVO:
 +
1) Guardar MediaWiki:Common.js (reemplazar TODO el contenido anterior)
 +
2) Purgar caché: /index.php?title=Página_principal&action=purge
 +
3) Recargar duro: Ctrl+F5
 +
4) Probar:
 +
  - Click en el botón flotante WIKICONSULTAS (abajo derecha)
 +
  - Click en el botón de la página con id="wk-open" (si lo usas)
 +
  - Abrir URL con #wikiconsultas
 +
*/

Revisión actual del 10:36 6 feb 2026

/* ==========================================================
   WIKICONSULTAS – Chat de consultas
   Especializado en: Piragüismo en Aranjuez
   Ubicación: MediaWiki:Common.js
   ========================================================== */

(function () {
  'use strict';

  // ================= CONFIGURACIÓN =================
  // Sustituye esta URL por el webhook de Make cuando lo tengas
  var WIKICONSULTAS_ENDPOINT = 'https://TU-DOMINIO.com/wikiconsultas';

  var SCOPE_NOTICE = 'Puedo ayudarte solo con consultas sobre el piragüismo en Aranjuez basándome en el contenido de esta wiki.';

  // ================= ESTILOS =================
  function addStyles() {
    mw.util.addCSS(`
      #wikiconsultas-btn{
        position:fixed; right:18px; bottom:18px; z-index:9999;
        padding:10px 14px; border-radius:999px; border:1px solid rgba(0,0,0,.15);
        background:#fff; cursor:pointer; box-shadow:0 6px 18px rgba(0,0,0,.18);
        font-weight:600;
      }
      #wikiconsultas-overlay{
        position:fixed; inset:0; z-index:99999; background:rgba(0,0,0,.45);
        display:none; align-items:center; justify-content:center; padding:18px;
      }
      #wikiconsultas-modal{
        width:min(760px, 96vw); height:min(560px, 86vh);
        background:#fff; border-radius:14px; overflow:hidden;
        box-shadow:0 14px 40px rgba(0,0,0,.25);
        display:flex; flex-direction:column;
      }
      #wikiconsultas-head{
        display:flex; align-items:center; justify-content:space-between;
        padding:12px 14px; border-bottom:1px solid rgba(0,0,0,.10);
      }
      #wikiconsultas-title{ font-size:16px; font-weight:700; }
      #wikiconsultas-close{
        border:0; background:transparent; cursor:pointer; font-size:20px; line-height:1;
        padding:6px 10px; border-radius:10px;
      }
      #wikiconsultas-close:hover{ background:rgba(0,0,0,.06); }
      #wikiconsultas-scope{
        padding:10px 14px; font-size:13px; color:#333;
        background:rgba(0,0,0,.03); border-bottom:1px solid rgba(0,0,0,.08);
      }
      #wikiconsultas-log{
        padding:14px; overflow:auto; flex:1; background:#fafafa;
      }
      .wk-msg{ margin:0 0 10px 0; display:flex; gap:10px; }
      .wk-badge{
        width:28px; height:28px; border-radius:50%;
        display:flex; align-items:center; justify-content:center;
        font-weight:700; font-size:12px; flex:0 0 auto;
        border:1px solid rgba(0,0,0,.12); background:#fff;
      }
      .wk-bubble{
        padding:10px 12px; border-radius:12px; max-width:85%;
        border:1px solid rgba(0,0,0,.10); background:#fff;
        white-space:pre-wrap;
      }
      #wikiconsultas-foot{
        padding:10px; border-top:1px solid rgba(0,0,0,.10);
        display:flex; gap:10px; background:#fff;
      }
      #wikiconsultas-input{
        flex:1; padding:10px 12px; border-radius:10px;
        border:1px solid rgba(0,0,0,.18);
      }
      #wikiconsultas-send{
        padding:10px 14px; border-radius:10px; border:1px solid rgba(0,0,0,.18);
        background:#fff; cursor:pointer; font-weight:700;
      }
      #wikiconsultas-send:hover{ background:rgba(0,0,0,.04); }
    `);
  }

  // ================= DOM HELPERS =================
  function el(tag, attrs, children) {
    var node = document.createElement(tag);
    if (attrs) Object.keys(attrs).forEach(function (k) { node.setAttribute(k, attrs[k]); });
    (children || []).forEach(function (c) {
      node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c);
    });
    return node;
  }

  function appendMsg(log, who, text) {
    var msg = el('div', { class: 'wk-msg' }, [
      el('div', { class: 'wk-badge' }, [who === 'user' ? 'Tú' : 'WK']),
      el('div', { class: 'wk-bubble' }, [text])
    ]);
    log.appendChild(msg);
    log.scrollTop = log.scrollHeight;
  }

  function openModal(overlay, input) {
    overlay.style.display = 'flex';
    setTimeout(function () { input.focus(); }, 50);
  }

  function closeModal(overlay) {
    overlay.style.display = 'none';
  }

  // ================= BACKEND =================
  async function askBackend(question) {
    if (!WIKICONSULTAS_ENDPOINT || WIKICONSULTAS_ENDPOINT.indexOf('TU-DOMINIO.com') !== -1) {
      return 'WIKICONSULTAS aún no está conectado a un servicio de IA.\n\nCuando tengas el webhook de Make, sustituye WIKICONSULTAS_ENDPOINT en MediaWiki:Common.js.';
    }

    var payload = {
      assistant: 'WIKICONSULTAS',
      scope: 'Piragüismo en Aranjuez',
      question: question,
      pageTitle: mw.config.get('wgTitle'),
      pageName: mw.config.get('wgPageName'),
      url: location.href,
      language: 'es'
    };

    var res = await fetch(WIKICONSULTAS_ENDPOINT, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });

    if (!res.ok) throw new Error('HTTP ' + res.status);
    var data = await res.json();
    return data && data.answer ? data.answer : 'No se recibió respuesta válida del servicio.';
  }

  // ================= INIT =================
  function init() {
    if (document.getElementById('wikiconsultas-btn')) return;

    addStyles();

    // UI
    var btn = el('button', { id: 'wikiconsultas-btn', type: 'button', title: 'Abrir WIKICONSULTAS' }, ['WIKICONSULTAS']);
    var overlay = el('div', { id: 'wikiconsultas-overlay', role: 'dialog', 'aria-modal': 'true' });
    var modal = el('div', { id: 'wikiconsultas-modal' });

    var head = el('div', { id: 'wikiconsultas-head' }, [
      el('div', { id: 'wikiconsultas-title' }, ['WIKICONSULTAS']),
      el('button', { id: 'wikiconsultas-close', type: 'button', title: 'Cerrar' }, ['×'])
    ]);

    var scope = el('div', { id: 'wikiconsultas-scope' }, [SCOPE_NOTICE]);
    var log = el('div', { id: 'wikiconsultas-log' });
    var foot = el('div', { id: 'wikiconsultas-foot' });
    var input = el('input', { id: 'wikiconsultas-input', type: 'text', placeholder: 'Escribe tu consulta…' });
    var send = el('button', { id: 'wikiconsultas-send', type: 'button' }, ['Enviar']);

    foot.appendChild(input);
    foot.appendChild(send);

    modal.appendChild(head);
    modal.appendChild(scope);
    modal.appendChild(log);
    modal.appendChild(foot);
    overlay.appendChild(modal);

    document.body.appendChild(btn);
    document.body.appendChild(overlay);

    // Mensaje inicial
    appendMsg(log, 'bot', 'Hola 👋 Soy WIKICONSULTAS.\nHazme preguntas sobre el piragüismo en Aranjuez basándome en el contenido de esta wiki.');

    // Eventos básicos
    btn.addEventListener('click', function () { openModal(overlay, input); });
    document.getElementById('wikiconsultas-close').addEventListener('click', function () { closeModal(overlay); });
    overlay.addEventListener('click', function (e) { if (e.target === overlay) closeModal(overlay); });

    async function doSend() {
      var q = (input.value || '').trim();
      if (!q) return;

      appendMsg(log, 'user', q);
      input.value = '';
      appendMsg(log, 'bot', 'Pensando…');
      var thinkingNode = log.lastChild;

      try {
        var answer = await askBackend(q);
        thinkingNode.querySelector('.wk-bubble').textContent = answer;
      } catch (err) {
        thinkingNode.querySelector('.wk-bubble').textContent = 'No he podido conectar con el servicio.\n\nDetalles: ' + (err && err.message ? err.message : String(err));
      }
    }

    send.addEventListener('click', doSend);
    input.addEventListener('keydown', function (e) {
      if (e.key === 'Enter') doSend();
      if (e.key === 'Escape') closeModal(overlay);
    });

    // ==================================================
    // APERTURA ROBUSTA DESDE LA PÁGINA
    // 1) #wikiconsultas en la URL
    // 2) Clic en cualquier enlace que contenga #wikiconsultas
    // 3) Clic en el “botón” de la página con id="wk-open"
    // ==================================================

    function openIfHash() {
      if (location.hash === '#wikiconsultas') {
        openModal(overlay, input);
      }
    }

    // Abre si carga con el hash
    openIfHash();

    // Abre si cambia el hash
    window.addEventListener('hashchange', openIfHash);

    // Captura clics (enlaces con #wikiconsultas)
    document.addEventListener('click', function (e) {
      var a = e.target && e.target.closest ? e.target.closest('a') : null;
      if (!a) return;

      var href = a.getAttribute('href') || '';
      if (href.indexOf('#wikiconsultas') !== -1) {
        e.preventDefault();
        e.stopPropagation();
        try {
          if (location.hash !== '#wikiconsultas') history.pushState(null, '', '#wikiconsultas');
        } catch (_) {}
        openModal(overlay, input);
      }
    }, true);

    // Clic directo en el “botón” embebido en la página principal
    document.addEventListener('click', function (e) {
      var node = e.target && e.target.closest ? e.target.closest('#wk-open') : null;
      if (!node) return;
      e.preventDefault();
      e.stopPropagation();
      try {
        if (location.hash !== '#wikiconsultas') history.pushState(null, '', '#wikiconsultas');
      } catch (_) {}
      openModal(overlay, input);
    }, true);
  }

  mw.loader.using(['mediawiki.util']).then(init);
})();

/*
PASOS TRAS PEGAR ESTE ARCHIVO:
1) Guardar MediaWiki:Common.js (reemplazar TODO el contenido anterior)
2) Purgar caché: /index.php?title=Página_principal&action=purge
3) Recargar duro: Ctrl+F5
4) Probar:
   - Click en el botón flotante WIKICONSULTAS (abajo derecha)
   - Click en el botón de la página con id="wk-open" (si lo usas)
   - Abrir URL con #wikiconsultas
*/