Plugin Directory

Changeset 3489921


Ignore:
Timestamp:
03/24/2026 11:35:51 AM (8 days ago)
Author:
setglobaldev
Message:

Release 1.2.9: onboarding checklist alignment, notification smoke test, KPI tracking, i18n updates

Location:
setchat/trunk
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • setchat/trunk/assets/admin.css

    r3483972 r3489921  
    4040    border: 1px solid #fca5a5;
    4141}
     42
     43.setchat-checklist {
     44    margin-top: 12px;
     45}
     46
     47.setchat-checklist-title {
     48    font-weight: 600;
     49    margin-bottom: 8px;
     50    font-size: 13px;
     51}
     52
     53.setchat-checklist-item {
     54    display: flex;
     55    align-items: center;
     56    justify-content: space-between;
     57    gap: 12px;
     58    padding: 8px 10px;
     59    border-radius: 8px;
     60    border: 1px solid #e5e7eb;
     61    margin-top: 8px;
     62}
     63
     64.setchat-checklist-label {
     65    font-size: 13px;
     66    color: #111827;
     67}
     68
     69.setchat-checklist-state {
     70    font-size: 12px;
     71    font-weight: 700;
     72    padding: 4px 8px;
     73    border-radius: 999px;
     74    background: #f3f4f6;
     75    color: #4b5563;
     76    white-space: nowrap;
     77}
     78
     79.setchat-status-ok {
     80    border-color: #6ee7b7;
     81    background: #ecfdf5;
     82}
     83.setchat-status-ok .setchat-checklist-state {
     84    background: #d1fae5;
     85    color: #065f46;
     86}
     87
     88.setchat-status-missing {
     89    border-color: #fbbf24;
     90    background: #fffbeb;
     91}
     92.setchat-status-missing .setchat-checklist-state {
     93    background: #fef3c7;
     94    color: #92400e;
     95}
     96
     97.setchat-status-error {
     98    border-color: #fca5a5;
     99    background: #fef2f2;
     100}
     101.setchat-status-error .setchat-checklist-state {
     102    background: #fee2e2;
     103    color: #991b1b;
     104}
     105
     106.setchat-status-pending {
     107    border-color: #e5e7eb;
     108}
     109
     110.setchat-status-badge {
     111    display: inline-block;
     112    font-size: 11px;
     113    font-weight: 700;
     114    line-height: 1;
     115    padding: 4px 8px;
     116    border-radius: 999px;
     117    margin-right: 8px;
     118}
     119
     120.setchat-status-badge-ok {
     121    background: #d1fae5;
     122    color: #065f46;
     123    border: 1px solid #6ee7b7;
     124}
     125
     126.setchat-status-badge-warn {
     127    background: #fef3c7;
     128    color: #92400e;
     129    border: 1px solid #fbbf24;
     130}
  • setchat/trunk/assets/admin.js

    r3483972 r3489921  
    33
    44    var btn = document.getElementById('setchat-test-btn');
     5    var notifBtn = document.getElementById('setchat-test-notification-btn');
    56    var resultEl = document.getElementById('setchat-test-result');
     7    var lastNotifEl = document.getElementById('setchat-last-notification-test');
     8    var checklistEl = document.getElementById('setchat-checklist');
     9
     10    var apiKeyStateEl = document.getElementById('setchat-checklist-api-key-state');
     11    var widgetConfigStateEl = document.getElementById('setchat-checklist-widget-config-state');
     12    var siteStateEl = document.getElementById('setchat-checklist-site-state');
     13    var liveTestStateEl = document.getElementById('setchat-checklist-live-test-state');
     14    var notificationsStateEl = document.getElementById('setchat-checklist-notifications-state');
     15    var doneStateEl = document.getElementById('setchat-checklist-done-state');
     16
     17    var ctaFaq = document.getElementById('setchat-cta-faq');
     18    var ctaFlows = document.getElementById('setchat-cta-flows');
     19    var ctaSites = document.getElementById('setchat-cta-sites');
     20    var ctaLiveTest = document.getElementById('setchat-cta-livetest');
     21    var ctaNotifications = document.getElementById('setchat-cta-notifications');
    622    if (!btn || !resultEl) return;
    723
    8     btn.addEventListener('click', function () {
     24    function setChecklistStatus(itemId, stateEl, statusType, statusText) {
     25      var itemEl = document.getElementById(itemId);
     26      if (!itemEl || !stateEl) return;
     27      itemEl.classList.remove('setchat-status-ok', 'setchat-status-missing', 'setchat-status-error', 'setchat-status-pending');
     28      itemEl.classList.add('setchat-status-' + statusType);
     29      stateEl.textContent = statusText;
     30    }
     31
     32    function renderLastNotificationTest(data) {
     33      if (!lastNotifEl) return;
     34      var testedAt = (data && data.testedAt) ? String(data.testedAt) : '';
     35      var emailTriggered = !!(data && data.emailTriggered);
     36      var teamsTriggered = !!(data && data.teamsTriggered);
     37
     38      if (!testedAt) {
     39        lastNotifEl.innerHTML =
     40          '<span class="setchat-status-badge setchat-status-badge-warn">' +
     41          (setchatAdmin.i18n.notifStatusNeedsAction || 'Action needed') +
     42          '</span> ' +
     43          (setchatAdmin.i18n.notifStatusPrefix || 'Last notification test:') + ' ' + (setchatAdmin.i18n.notifStatusNever || 'No test yet');
     44        return;
     45      }
     46
     47      var channels = [];
     48      if (emailTriggered) channels.push('email');
     49      if (teamsTriggered) channels.push('teams');
     50      var channelsText = channels.length ? channels.join(' + ') : '-';
     51      var healthy = channels.length > 0;
     52      var badgeClass = healthy ? 'setchat-status-badge-ok' : 'setchat-status-badge-warn';
     53      var badgeLabel = healthy
     54        ? (setchatAdmin.i18n.notifStatusHealthy || 'Healthy')
     55        : (setchatAdmin.i18n.notifStatusNeedsAction || 'Action needed');
     56      lastNotifEl.textContent =
     57        '';
     58      lastNotifEl.innerHTML =
     59        '<span class="setchat-status-badge ' + badgeClass + '">' + badgeLabel + '</span> ' +
     60        (setchatAdmin.i18n.notifStatusPrefix || 'Last notification test:') +
     61        ' ' + testedAt +
     62        ' | ' +
     63        (setchatAdmin.i18n.notifStatusChannels || 'Channels') +
     64        ': ' + channelsText;
     65    }
     66
     67    function trackEvent(eventName, metadata) {
     68      var keyInput = document.getElementById('setchat_api_key');
     69      var apiKey = keyInput ? keyInput.value.trim() : '';
     70      if (!apiKey || !eventName) return;
     71      var data = new FormData();
     72      data.append('action', 'setchat_track_event');
     73      data.append('nonce', setchatAdmin.nonce);
     74      data.append('api_key', apiKey);
     75      data.append('event', eventName);
     76      data.append('metadata', JSON.stringify(metadata || {}));
     77      fetch(setchatAdmin.ajaxUrl, { method: 'POST', body: data }).catch(function () {});
     78    }
     79
     80    function runTestConnection() {
    981        var keyInput = document.getElementById('setchat_api_key');
    1082        var apiKey = keyInput ? keyInput.value.trim() : '';
     
    1587        }
    1688
     89        var keyInput = document.getElementById('setchat_api_key');
    1790        btn.disabled = true;
    1891        btn.textContent = setchatAdmin.i18n.testing;
    1992        resultEl.style.display = 'none';
     93        if (checklistEl) checklistEl.style.display = 'none';
    2094
    2195        var data = new FormData();
     
    33107                    }
    34108                    showResult('success', msg);
     109
     110                    if (checklistEl) {
     111                      ctaFaq && (ctaFaq.href = setchatAdmin.dashboardFaqUrl);
     112                      ctaFlows && (ctaFlows.href = setchatAdmin.dashboardFlowsUrl);
     113                      ctaSites && (ctaSites.href = setchatAdmin.dashboardSitesUrl);
     114                      ctaLiveTest && (ctaLiveTest.href = setchatAdmin.dashboardLiveTestUrl);
     115                      ctaNotifications && (ctaNotifications.href = setchatAdmin.dashboardNotificationsUrl);
     116                      checklistEl.style.display = 'block';
     117
     118                      setChecklistStatus('setchat-checklist-api-key', apiKeyStateEl, 'ok', setchatAdmin.i18n.statusOk);
     119                      setChecklistStatus('setchat-checklist-widget-config', widgetConfigStateEl, 'ok', setchatAdmin.i18n.statusOk);
     120
     121                      var activationReady = (res.data && res.data.activationReady) ? res.data.activationReady : {};
     122                      var hasSite = !!activationReady.hasSite;
     123                      var liveTestDetected = !!activationReady.liveTestDetected;
     124                      var notificationsReady = !!activationReady.notificationsReady;
     125                      var done = !!activationReady.done;
     126
     127                      setChecklistStatus(
     128                        'setchat-checklist-site',
     129                        siteStateEl,
     130                        hasSite ? 'ok' : 'missing',
     131                        hasSite ? setchatAdmin.i18n.statusOk : setchatAdmin.i18n.statusMissing
     132                      );
     133
     134                      setChecklistStatus(
     135                        'setchat-checklist-live-test',
     136                        liveTestStateEl,
     137                        liveTestDetected ? 'ok' : 'missing',
     138                        liveTestDetected ? setchatAdmin.i18n.statusOk : setchatAdmin.i18n.statusMissing
     139                      );
     140
     141                      setChecklistStatus(
     142                        'setchat-checklist-notifications',
     143                        notificationsStateEl,
     144                        notificationsReady ? 'ok' : 'missing',
     145                        notificationsReady ? setchatAdmin.i18n.statusOk : setchatAdmin.i18n.statusMissing
     146                      );
     147
     148                      setChecklistStatus(
     149                        'setchat-checklist-done',
     150                        doneStateEl,
     151                        done ? 'ok' : 'missing',
     152                        done ? setchatAdmin.i18n.doneYes : setchatAdmin.i18n.doneNo
     153                      );
     154
     155                      function setCtaVisible(el, visible) {
     156                        if (!el) return;
     157                        el.style.display = visible ? '' : 'none';
     158                      }
     159
     160                      setCtaVisible(ctaSites, !hasSite);
     161                      setCtaVisible(ctaLiveTest, !liveTestDetected);
     162                      setCtaVisible(ctaNotifications, !notificationsReady);
     163
     164                      // These optional CTAs help conversion after the core readiness gates.
     165                      if (ctaFaq) ctaFaq.style.display = done ? '' : 'none';
     166                      if (ctaFlows) ctaFlows.style.display = done ? '' : 'none';
     167
     168                      trackEvent('wp_plugin_connected', { done: done });
     169                      if (hasSite) trackEvent('wp_step_site_ok', {});
     170                      if (liveTestDetected) trackEvent('wp_step_live_test_ok', {});
     171                      if (notificationsReady) trackEvent('wp_step_notifications_ok', {});
     172                      if (done) trackEvent('wp_onboarding_done', {});
     173                    }
    35174                } else {
    36175                    var errMsg = (res.data && res.data.message) || setchatAdmin.i18n.error;
    37176                    showResult('error', errMsg);
     177
     178                    if (checklistEl) {
     179                      checklistEl.style.display = 'block';
     180                      setChecklistStatus('setchat-checklist-api-key', apiKeyStateEl, 'error', setchatAdmin.i18n.statusError);
     181                      setChecklistStatus('setchat-checklist-widget-config', widgetConfigStateEl, 'error', setchatAdmin.i18n.statusError);
     182
     183                      setChecklistStatus('setchat-checklist-site', siteStateEl, 'pending', setchatAdmin.i18n.statusPending);
     184                      setChecklistStatus('setchat-checklist-live-test', liveTestStateEl, 'pending', setchatAdmin.i18n.statusPending);
     185                      setChecklistStatus('setchat-checklist-notifications', notificationsStateEl, 'pending', setchatAdmin.i18n.statusPending);
     186                      setChecklistStatus('setchat-checklist-done', doneStateEl, 'pending', setchatAdmin.i18n.statusPending);
     187                    }
    38188                }
    39189            })
     
    45195                btn.textContent = setchatAdmin.i18n.testBtn;
    46196            });
     197    }
     198
     199    function runTestNotification() {
     200        var keyInput = document.getElementById('setchat_api_key');
     201        var apiKey = keyInput ? keyInput.value.trim() : '';
     202        if (!apiKey) {
     203            showResult('error', setchatAdmin.i18n.noKey);
     204            return;
     205        }
     206
     207        if (notifBtn) {
     208          notifBtn.disabled = true;
     209          notifBtn.textContent = setchatAdmin.i18n.testingNotifBtn || setchatAdmin.i18n.testNotifBtn;
     210        }
     211
     212        var data = new FormData();
     213        data.append('action', 'setchat_test_notification');
     214        data.append('nonce', setchatAdmin.nonce);
     215        data.append('api_key', apiKey);
     216
     217        fetch(setchatAdmin.ajaxUrl, { method: 'POST', body: data })
     218          .then(function (res) { return res.json(); })
     219          .then(function (res) {
     220            if (!res.success) {
     221              var errMsg = (res.data && res.data.message) || setchatAdmin.i18n.error;
     222              showResult('error', errMsg);
     223              return;
     224            }
     225
     226            var emailTriggered = !!(res.data && res.data.emailTriggered);
     227            var teamsTriggered = !!(res.data && res.data.teamsTriggered);
     228            var details = [];
     229            if (emailTriggered) details.push('email');
     230            if (teamsTriggered) details.push('teams');
     231            var suffix = details.length ? ' (' + details.join(' + ') + ')' : '';
     232            showResult('success', (setchatAdmin.i18n.notifSuccess || setchatAdmin.i18n.success) + suffix);
     233            renderLastNotificationTest({
     234              testedAt: (res.data && res.data.testedAt) ? res.data.testedAt : '',
     235              emailTriggered: emailTriggered,
     236              teamsTriggered: teamsTriggered
     237            });
     238
     239            // Refresh checklist after a successful notification test.
     240            runTestConnection();
     241          })
     242          .catch(function () {
     243            showResult('error', setchatAdmin.i18n.networkErr);
     244          })
     245          .finally(function () {
     246            if (notifBtn) {
     247              notifBtn.disabled = false;
     248              notifBtn.textContent = setchatAdmin.i18n.testNotifBtn || 'Test notification';
     249            }
     250          });
     251    }
     252
     253    btn.addEventListener('click', function () {
     254      runTestConnection();
    47255    });
     256    if (notifBtn) {
     257      notifBtn.addEventListener('click', function () {
     258        trackEvent('wp_cta_clicked', { cta: 'test_notification' });
     259        runTestNotification();
     260      });
     261    }
     262    if (ctaSites) ctaSites.addEventListener('click', function () { trackEvent('wp_cta_clicked', { cta: 'sites' }); });
     263    if (ctaLiveTest) ctaLiveTest.addEventListener('click', function () { trackEvent('wp_cta_clicked', { cta: 'livetest' }); });
     264    if (ctaNotifications) ctaNotifications.addEventListener('click', function () { trackEvent('wp_cta_clicked', { cta: 'notifications' }); });
     265    if (ctaFaq) ctaFaq.addEventListener('click', function () { trackEvent('wp_cta_clicked', { cta: 'faq' }); });
     266    if (ctaFlows) ctaFlows.addEventListener('click', function () { trackEvent('wp_cta_clicked', { cta: 'flows' }); });
    48267
    49268    function showResult(type, message) {
     
    52271        resultEl.style.display = 'block';
    53272    }
     273
     274    // Auto-diagnose: if API key is already present, run a test once.
     275    renderLastNotificationTest(setchatAdmin.lastNotificationTest || null);
     276    var keyInput = document.getElementById('setchat_api_key');
     277    if (keyInput && keyInput.value && keyInput.value.trim() && !btn.disabled) {
     278      trackEvent('wp_activation_status_viewed', {});
     279      runTestConnection();
     280    }
    54281})();
  • setchat/trunk/languages/setchat-de_DE.po

    r3483972 r3489921  
    155155msgid "Chat with us"
    156156msgstr "Chatten Sie mit uns"
     157
     158#: setchat.php
     159msgid "Test connection"
     160msgstr "Verbindung testen"
     161
     162#: setchat.php
     163msgid "Connection successful! Your API key is valid."
     164msgstr "Verbindung erfolgreich! Ihr API-Schluessel ist gueltig."
     165
     166#: setchat.php
     167msgid "Connection failed. Please check your API key."
     168msgstr "Verbindung fehlgeschlagen. Bitte pruefen Sie Ihren API-Schluessel."
     169
     170#: setchat.php
     171msgid "Please enter an API key first."
     172msgstr "Bitte geben Sie zuerst einen API-Schluessel ein."
     173
     174#: setchat.php
     175msgid "Network error. Please try again."
     176msgstr "Netzwerkfehler. Bitte versuchen Sie es erneut."
     177
     178#: setchat.php
     179msgid "Activation checklist"
     180msgstr "Aktivierungs-Checkliste"
     181
     182#: setchat.php
     183msgid "OK"
     184msgstr "OK"
     185
     186#: setchat.php
     187msgid "Pending"
     188msgstr "Ausstehend"
     189
     190#: setchat.php
     191msgid "Missing"
     192msgstr "Fehlt"
     193
     194#: setchat.php
     195msgid "Error"
     196msgstr "Fehler"
     197
     198#: setchat.php
     199msgid "API key works"
     200msgstr "API-Schluessel funktioniert"
     201
     202#: setchat.php
     203msgid "Widget config loaded"
     204msgstr "Widget-Konfiguration geladen"
     205
     206#: setchat.php
     207msgid "Site configured"
     208msgstr "Website konfiguriert"
     209
     210#: setchat.php
     211msgid "Live test detected"
     212msgstr "Live-Test erkannt"
     213
     214#: setchat.php
     215msgid "Notifications ready"
     216msgstr "Benachrichtigungen bereit"
     217
     218#: setchat.php
     219msgid "Ready for conversion"
     220msgstr "Bereit fuer Konvertierung"
     221
     222#: setchat.php
     223msgid "Yes - ready"
     224msgstr "Ja - bereit"
     225
     226#: setchat.php
     227msgid "Not yet"
     228msgstr "Noch nicht"
     229
     230#: setchat.php
     231msgid "Configure FAQ/KB"
     232msgstr "FAQ/KB konfigurieren"
     233
     234#: setchat.php
     235msgid "Create first flow"
     236msgstr "Ersten Flow erstellen"
     237
     238#: setchat.php
     239msgid "Configure sites"
     240msgstr "Websites konfigurieren"
     241
     242#: setchat.php
     243msgid "Run live test"
     244msgstr "Live-Test starten"
     245
     246#: setchat.php
     247msgid "Configure notifications"
     248msgstr "Benachrichtigungen konfigurieren"
     249
     250#: setchat.php
     251msgid "Unauthorized"
     252msgstr "Nicht autorisiert"
     253
     254#: setchat.php
     255msgid "No API key provided"
     256msgstr "Kein API-Schluessel angegeben"
     257
     258#: setchat.php
     259msgid "Add a professional live chat widget to your WordPress site. FAQ chatbot, conversational flows, ticketing and more."
     260msgstr "Fuegen Sie Ihrer WordPress-Website ein professionelles Live-Chat-Widget hinzu. FAQ-Chatbot, konversationelle Flows, Ticketing und mehr."
     261
     262#: setchat.php
     263msgid "Test notification"
     264msgstr "Benachrichtigung testen"
     265
     266#: setchat.php
     267msgid "Testing notification…"
     268msgstr "Benachrichtigung wird getestet…"
     269
     270#: setchat.php
     271msgid "Notification test triggered successfully."
     272msgstr "Benachrichtigungstest erfolgreich ausgeloest."
     273
     274#: setchat.php
     275msgid "Notifications are not configured yet. Please configure notifications first."
     276msgstr "Benachrichtigungen sind noch nicht konfiguriert. Bitte konfigurieren Sie zuerst die Benachrichtigungen."
     277
     278#: setchat.php
     279msgid "Notification test failed"
     280msgstr "Benachrichtigungstest fehlgeschlagen"
     281
     282#: setchat.php
     283msgid "Last notification test:"
     284msgstr "Letzter Benachrichtigungstest:"
     285
     286#: setchat.php
     287msgid "No test yet"
     288msgstr "Noch kein Test"
     289
     290#: setchat.php
     291msgid "Channels"
     292msgstr "Kanaele"
     293
     294#: setchat.php
     295msgid "Healthy"
     296msgstr "Gesund"
     297
     298#: setchat.php
     299msgid "Action needed"
     300msgstr "Aktion erforderlich"
     301
     302#: setchat.php
     303msgid "Bad request"
     304msgstr "Ungueltige Anfrage"
     305
     306#: setchat.php
     307msgid "Analytics event failed"
     308msgstr "Analytics-Ereignis fehlgeschlagen"
  • setchat/trunk/languages/setchat-fr_FR.po

    r3483972 r3489921  
    155155msgid "Chat with us"
    156156msgstr "Discutons"
     157
     158#: setchat.php
     159msgid "Test connection"
     160msgstr "Tester la connexion"
     161
     162#: setchat.php
     163msgid "Connection successful! Your API key is valid."
     164msgstr "Connexion réussie ! Votre clé API est valide."
     165
     166#: setchat.php
     167msgid "Connection failed. Please check your API key."
     168msgstr "Échec de connexion. Vérifiez votre clé API."
     169
     170#: setchat.php
     171msgid "Please enter an API key first."
     172msgstr "Veuillez d'abord saisir une clé API."
     173
     174#: setchat.php
     175msgid "Network error. Please try again."
     176msgstr "Erreur réseau. Veuillez réessayer."
     177
     178#: setchat.php
     179msgid "Activation checklist"
     180msgstr "Checklist d'activation"
     181
     182#: setchat.php
     183msgid "OK"
     184msgstr "OK"
     185
     186#: setchat.php
     187msgid "Pending"
     188msgstr "En attente"
     189
     190#: setchat.php
     191msgid "Missing"
     192msgstr "Manquant"
     193
     194#: setchat.php
     195msgid "Error"
     196msgstr "Erreur"
     197
     198#: setchat.php
     199msgid "API key works"
     200msgstr "Clé API valide"
     201
     202#: setchat.php
     203msgid "Widget config loaded"
     204msgstr "Configuration du widget chargée"
     205
     206#: setchat.php
     207msgid "Site configured"
     208msgstr "Site configuré"
     209
     210#: setchat.php
     211msgid "Live test detected"
     212msgstr "Test live détecté"
     213
     214#: setchat.php
     215msgid "Notifications ready"
     216msgstr "Notifications prêtes"
     217
     218#: setchat.php
     219msgid "Ready for conversion"
     220msgstr "Prêt pour conversion"
     221
     222#: setchat.php
     223msgid "Yes - ready"
     224msgstr "Oui - prêt"
     225
     226#: setchat.php
     227msgid "Not yet"
     228msgstr "Pas encore"
     229
     230#: setchat.php
     231msgid "Configure FAQ/KB"
     232msgstr "Configurer la FAQ/KB"
     233
     234#: setchat.php
     235msgid "Create first flow"
     236msgstr "Créer le premier flow"
     237
     238#: setchat.php
     239msgid "Configure sites"
     240msgstr "Configurer les sites"
     241
     242#: setchat.php
     243msgid "Run live test"
     244msgstr "Lancer un test live"
     245
     246#: setchat.php
     247msgid "Configure notifications"
     248msgstr "Configurer les notifications"
     249
     250#: setchat.php
     251msgid "Unauthorized"
     252msgstr "Non autorise"
     253
     254#: setchat.php
     255msgid "No API key provided"
     256msgstr "Aucune clé API fournie"
     257
     258#: setchat.php
     259msgid "Add a professional live chat widget to your WordPress site. FAQ chatbot, conversational flows, ticketing and more."
     260msgstr "Ajoutez un widget de chat en direct professionnel à votre site WordPress. Chatbot FAQ, flows conversationnels, ticketing et plus encore."
     261
     262#: setchat.php
     263msgid "Test notification"
     264msgstr "Tester la notification"
     265
     266#: setchat.php
     267msgid "Testing notification…"
     268msgstr "Test de notification…"
     269
     270#: setchat.php
     271msgid "Notification test triggered successfully."
     272msgstr "Test de notification déclenché avec succès."
     273
     274#: setchat.php
     275msgid "Notifications are not configured yet. Please configure notifications first."
     276msgstr "Les notifications ne sont pas encore configurées. Veuillez d'abord configurer les notifications."
     277
     278#: setchat.php
     279msgid "Notification test failed"
     280msgstr "Le test de notification a échoué"
     281
     282#: setchat.php
     283msgid "Last notification test:"
     284msgstr "Dernier test de notification :"
     285
     286#: setchat.php
     287msgid "No test yet"
     288msgstr "Aucun test pour le moment"
     289
     290#: setchat.php
     291msgid "Channels"
     292msgstr "Canaux"
     293
     294#: setchat.php
     295msgid "Healthy"
     296msgstr "Sain"
     297
     298#: setchat.php
     299msgid "Action needed"
     300msgstr "Action requise"
     301
     302#: setchat.php
     303msgid "Bad request"
     304msgstr "Requête invalide"
     305
     306#: setchat.php
     307msgid "Analytics event failed"
     308msgstr "Échec de l'événement analytics"
  • setchat/trunk/languages/setchat.pot

    r3483972 r3489921  
    153153msgid "Chat with us"
    154154msgstr ""
     155
     156#: setchat.php
     157msgid "Test connection"
     158msgstr ""
     159
     160#: setchat.php
     161msgid "Connection successful! Your API key is valid."
     162msgstr ""
     163
     164#: setchat.php
     165msgid "Connection failed. Please check your API key."
     166msgstr ""
     167
     168#: setchat.php
     169msgid "Please enter an API key first."
     170msgstr ""
     171
     172#: setchat.php
     173msgid "Network error. Please try again."
     174msgstr ""
     175
     176#: setchat.php
     177msgid "Activation checklist"
     178msgstr ""
     179
     180#: setchat.php
     181msgid "OK"
     182msgstr ""
     183
     184#: setchat.php
     185msgid "Pending"
     186msgstr ""
     187
     188#: setchat.php
     189msgid "Missing"
     190msgstr ""
     191
     192#: setchat.php
     193msgid "Error"
     194msgstr ""
     195
     196#: setchat.php
     197msgid "API key works"
     198msgstr ""
     199
     200#: setchat.php
     201msgid "Widget config loaded"
     202msgstr ""
     203
     204#: setchat.php
     205msgid "Site configured"
     206msgstr ""
     207
     208#: setchat.php
     209msgid "Live test detected"
     210msgstr ""
     211
     212#: setchat.php
     213msgid "Notifications ready"
     214msgstr ""
     215
     216#: setchat.php
     217msgid "Ready for conversion"
     218msgstr ""
     219
     220#: setchat.php
     221msgid "Yes - ready"
     222msgstr ""
     223
     224#: setchat.php
     225msgid "Not yet"
     226msgstr ""
     227
     228#: setchat.php
     229msgid "Configure FAQ/KB"
     230msgstr ""
     231
     232#: setchat.php
     233msgid "Create first flow"
     234msgstr ""
     235
     236#: setchat.php
     237msgid "Configure sites"
     238msgstr ""
     239
     240#: setchat.php
     241msgid "Run live test"
     242msgstr ""
     243
     244#: setchat.php
     245msgid "Configure notifications"
     246msgstr ""
     247
     248#: setchat.php
     249msgid "Unauthorized"
     250msgstr ""
     251
     252#: setchat.php
     253msgid "No API key provided"
     254msgstr ""
     255
     256#: setchat.php
     257msgid "Add a professional live chat widget to your WordPress site. FAQ chatbot, conversational flows, ticketing and more."
     258msgstr ""
     259
     260#: setchat.php
     261msgid "Test notification"
     262msgstr ""
     263
     264#: setchat.php
     265msgid "Testing notification…"
     266msgstr ""
     267
     268#: setchat.php
     269msgid "Notification test triggered successfully."
     270msgstr ""
     271
     272#: setchat.php
     273msgid "Notifications are not configured yet. Please configure notifications first."
     274msgstr ""
     275
     276#: setchat.php
     277msgid "Notification test failed"
     278msgstr ""
     279
     280#: setchat.php
     281msgid "Last notification test:"
     282msgstr ""
     283
     284#: setchat.php
     285msgid "No test yet"
     286msgstr ""
     287
     288#: setchat.php
     289msgid "Channels"
     290msgstr ""
     291
     292#: setchat.php
     293msgid "Healthy"
     294msgstr ""
     295
     296#: setchat.php
     297msgid "Action needed"
     298msgstr ""
     299
     300#: setchat.php
     301msgid "Bad request"
     302msgstr ""
     303
     304#: setchat.php
     305msgid "Analytics event failed"
     306msgstr ""
  • setchat/trunk/readme.txt

    r3483972 r3489921  
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.2.3
     7Stable tag: 1.2.9
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    9898
    9999== Upgrade Notice ==
     100== 1.2.9 ==
     101Improved: Added notification smoke-test button, notification health badge, and onboarding KPI event tracking in `Settings > SetChat`.
     102
     103== 1.2.8 ==
     104Improved: Checklist in `Settings > SetChat` now aligns with dashboard onboarding “done” signals (site + live test + notifications) to maximize trial conversion.
     105
     106== 1.2.7 ==
     107Improved: Gutenberg block icon + removed duplicate CSS class field.
     108
     109= 1.2.6 =
     110Improved: Activation checklist in `Settings > SetChat` (KB/flows/pre-chat readiness) + auto-diagnose.
     111
     112= 1.2.5 =
     113Improved: Gutenberg block editor UI (InspectorControls) for button text and CSS class.
     114
     115= 1.2.4 =
     116Improved: Widget colors customization + Gutenberg block `[setchat/chat]` for one-click widget opening.
    100117
    101118= 1.2.3 =
     
    106123
    107124== Changelog ==
     125
     126= 1.2.9 =
     127* Added: "Test notification" action in plugin settings (email/teams smoke test through API key).
     128* Added: Notification health status badge with last test timestamp and channels used.
     129* Added: Onboarding KPI instrumentation events (`WIDGET_EVENT`) for conversion funnel tracking.
     130
     131= 1.2.8 =
     132* Improved: Activation checklist updated to match dashboard “done” signals (site + live test + notifications).
     133
     134= 1.2.6 =
     135* Improved: Activation checklist in `Settings > SetChat`
     136
     137= 1.2.5 =
     138* Improved: Gutenberg editor UI for block `[setchat/chat]` (text/class)
     139
     140= 1.2.4 =
     141* Improved: Added Gutenberg block `[setchat/chat]` to open the widget
     142* Improved: Added optional widget color overrides (primary/secondary/accent)
    108143
    109144= 1.2.3 =
  • setchat/trunk/setchat.php

    r3483972 r3489921  
    44 * Plugin URI: https://setchat.co
    55 * Description: Add a professional live chat widget to your WordPress site. FAQ chatbot, conversational flows, ticketing and more.
    6  * Version: 1.2.3
     6 * Version: 1.2.9
    77 * Author: SetChat
    88 * Author URI: https://setglobal.co
     
    2222final class SetChat_Plugin {
    2323
    24     const VERSION          = '1.2.3';
     24    const VERSION          = '1.2.9';
    2525    const WIDGET_URL       = 'https://widget.setchat.co/setchat.iife.js';
    2626    const API_URL          = 'https://api.setchat.co';
     27    const DASHBOARD_URL   = 'https://app.setchat.co';
    2728    const ALLOWED_LOCALES  = ['', 'fr', 'en', 'de'];
    2829    const ALLOWED_POSITIONS = ['bottom-right', 'bottom-left'];
     
    3233
    3334    public function __construct() {
    34         // Translations are loaded automatically by WordPress.org since WP 4.6
    3535        add_action('admin_init', [$this, 'register_settings']);
    3636        add_action('admin_init', [$this, 'register_privacy_policy']);
     
    3939        add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
    4040        add_action('wp_enqueue_scripts', [$this, 'enqueue_widget']);
     41        add_action('init', [$this, 'register_gutenberg_block']);
     42        add_action('enqueue_block_editor_assets', [$this, 'enqueue_gutenberg_editor_assets']);
    4143        add_action('wp_ajax_setchat_test_connection', [$this, 'ajax_test_connection']);
     44        add_action('wp_ajax_setchat_test_notification', [$this, 'ajax_test_notification']);
     45        add_action('wp_ajax_setchat_track_event', [$this, 'ajax_track_event']);
    4246        add_filter('plugin_action_links_' . plugin_basename(__FILE__), [$this, 'plugin_action_links']);
    4347        add_shortcode('setchat', [$this, 'shortcode_render']);
     
    5559        add_option('setchat_woo_sync', true);
    5660        add_option('setchat_exclude_urls', '');
     61        add_option('setchat_primary_color', '');
     62        add_option('setchat_secondary_color', '');
     63        add_option('setchat_accent_color', '');
     64        add_option('setchat_last_notification_test', []);
    5765    }
    5866
     
    6270
    6371    /* ───── i18n ───── */
    64     // Translations are loaded automatically by WordPress.org hosting since WP 4.6
     72    // WordPress.org language packs are auto-loaded by core (WP >= 4.6).
    6573
    6674    /* ───── Sanitize helpers ───── */
     
    7482        $value = sanitize_text_field($value);
    7583        return in_array($value, self::ALLOWED_POSITIONS, true) ? $value : 'bottom-right';
     84    }
     85
     86    public function sanitize_hex_color($value) {
     87        $value = sanitize_text_field($value);
     88        $value = trim($value);
     89        if ($value === '') return '';
     90        // Accept #RGB or #RRGGBB
     91        if (preg_match('/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $value)) {
     92            return $value;
     93        }
     94        return '';
    7695    }
    7796
     
    117136            'type'              => 'string',
    118137            'sanitize_callback' => 'sanitize_textarea_field',
     138            'default'           => '',
     139        ]);
     140
     141        register_setting('setchat_options', 'setchat_primary_color', [
     142            'type'              => 'string',
     143            'sanitize_callback' => [$this, 'sanitize_hex_color'],
     144            'default'           => '',
     145        ]);
     146        register_setting('setchat_options', 'setchat_secondary_color', [
     147            'type'              => 'string',
     148            'sanitize_callback' => [$this, 'sanitize_hex_color'],
     149            'default'           => '',
     150        ]);
     151        register_setting('setchat_options', 'setchat_accent_color', [
     152            'type'              => 'string',
     153            'sanitize_callback' => [$this, 'sanitize_hex_color'],
    119154            'default'           => '',
    120155        ]);
     
    168203        );
    169204
     205        $last_notif_test = get_option('setchat_last_notification_test', []);
     206        $last_notif_payload = [
     207            'testedAt' => '',
     208            'emailTriggered' => false,
     209            'teamsTriggered' => false,
     210        ];
     211        if (is_array($last_notif_test)) {
     212            $last_notif_payload['testedAt'] = isset($last_notif_test['testedAt']) ? sanitize_text_field((string) $last_notif_test['testedAt']) : '';
     213            $last_notif_payload['emailTriggered'] = !empty($last_notif_test['emailTriggered']);
     214            $last_notif_payload['teamsTriggered'] = !empty($last_notif_test['teamsTriggered']);
     215        }
     216
    170217        wp_localize_script('setchat-admin', 'setchatAdmin', [
    171218            'ajaxUrl' => admin_url('admin-ajax.php'),
    172219            'nonce'   => wp_create_nonce('setchat_test_connection'),
     220            'dashboardFaqUrl' => self::DASHBOARD_URL . '/faq',
     221            'dashboardFlowsUrl' => self::DASHBOARD_URL . '/flows',
     222            'dashboardSitesUrl' => self::DASHBOARD_URL . '/sites',
     223            'dashboardLiveTestUrl' => self::DASHBOARD_URL . '/setup?step=5',
     224            'dashboardNotificationsUrl' => self::DASHBOARD_URL . '/settings?tab=notifications',
     225            'dashboardBillingUrl' => self::DASHBOARD_URL . '/settings?tab=billing',
     226            'lastNotificationTest' => $last_notif_payload,
    173227            'i18n'    => [
    174228                'testing'    => esc_html__('Testing…', 'setchat'),
    175229                'testBtn'    => esc_html__('Test connection', 'setchat'),
     230                'testingNotifBtn' => esc_html__('Testing notification…', 'setchat'),
     231                'testNotifBtn' => esc_html__('Test notification', 'setchat'),
    176232                'success'    => esc_html__('Connection successful! Your API key is valid.', 'setchat'),
     233                'notifSuccess' => esc_html__('Notification test triggered successfully.', 'setchat'),
     234                'notifStatusPrefix' => esc_html__('Last notification test:', 'setchat'),
     235                'notifStatusNever' => esc_html__('No test yet', 'setchat'),
     236                'notifStatusChannels' => esc_html__('Channels', 'setchat'),
     237                'notifStatusHealthy' => esc_html__('Healthy', 'setchat'),
     238                'notifStatusNeedsAction' => esc_html__('Action needed', 'setchat'),
    177239                'error'      => esc_html__('Connection failed. Please check your API key.', 'setchat'),
    178240                'noKey'      => esc_html__('Please enter an API key first.', 'setchat'),
    179241                'networkErr' => esc_html__('Network error. Please try again.', 'setchat'),
     242                'notifNotReady' => esc_html__('Notifications are not configured yet. Please configure notifications first.', 'setchat'),
     243                'checklistTitle' => esc_html__('Activation checklist', 'setchat'),
     244                'statusOk' => esc_html__('OK', 'setchat'),
     245                'statusPending' => esc_html__('Pending', 'setchat'),
     246                'statusMissing' => esc_html__('Missing', 'setchat'),
     247                'statusError' => esc_html__('Error', 'setchat'),
     248                'stepApiKey' => esc_html__('API key works', 'setchat'),
     249                'stepWidgetConfig' => esc_html__('Widget config loaded', 'setchat'),
     250                'stepSite' => esc_html__('Site configured', 'setchat'),
     251                'stepLiveTest' => esc_html__('Live test detected', 'setchat'),
     252                'stepNotifications' => esc_html__('Notifications ready', 'setchat'),
     253                'stepDone' => esc_html__('Ready for conversion', 'setchat'),
     254                'doneYes' => esc_html__('Yes - ready', 'setchat'),
     255                'doneNo' => esc_html__('Not yet', 'setchat'),
    180256            ],
    181257        ]);
     
    225301                : (isset($body['tenant']['name']) ? $body['tenant']['name'] : '');
    226302            $tenant_name = sanitize_text_field((string) $tenant_name_raw);
    227             wp_send_json_success(['tenantName' => $tenant_name]);
     303            $has_kb = !empty($body['hasKbArticles']);
     304
     305            $flow_buttons = $body['flowButtons'] ?? [];
     306            $flow_buttons_count = is_array($flow_buttons) ? count($flow_buttons) : 0;
     307
     308            $config = is_array($body['config'] ?? null) ? $body['config'] : [];
     309            $pre_chat_enabled = true;
     310            if (isset($config['preChatForm']) && is_array($config['preChatForm'])) {
     311                if (array_key_exists('enabled', $config['preChatForm'])) {
     312                    $pre_chat_enabled = $config['preChatForm']['enabled'] !== false;
     313                }
     314            }
     315
     316            $activation_ready = [
     317                'hasSite' => false,
     318                'notificationsReady' => false,
     319                'liveTestDetected' => false,
     320                'done' => false,
     321            ];
     322            $activation_response = wp_safe_remote_get(
     323                self::API_URL . '/api/widget/activation-status',
     324                [
     325                    'headers' => [
     326                        'x-api-key' => $api_key,
     327                        'Content-Type' => 'application/json',
     328                    ],
     329                    'timeout' => 10,
     330                ]
     331            );
     332            if (!is_wp_error($activation_response)) {
     333                $activation_code = wp_remote_retrieve_response_code($activation_response);
     334                $activation_body = json_decode(wp_remote_retrieve_body($activation_response), true);
     335                if ($activation_code >= 200 && $activation_code < 300 && is_array($activation_body)) {
     336                    $activation_ready = [
     337                        'hasSite' => !empty($activation_body['hasSite']),
     338                        'notificationsReady' => !empty($activation_body['notificationsReady']),
     339                        'liveTestDetected' => !empty($activation_body['liveTestDetected']),
     340                        'done' => !empty($activation_body['done']),
     341                    ];
     342                }
     343            }
     344
     345            wp_send_json_success([
     346                'tenantName' => $tenant_name,
     347                'hasKbArticles' => $has_kb,
     348                'flowButtonsCount' => $flow_buttons_count,
     349                'preChatFormEnabled' => $pre_chat_enabled,
     350                'activationReady' => $activation_ready,
     351            ]);
    228352        } else {
    229353            $message_raw = isset($body['message'])
     
    233357            wp_send_json_error(['message' => $message]);
    234358        }
     359    }
     360
     361    public function ajax_test_notification() {
     362        check_ajax_referer('setchat_test_connection', 'nonce');
     363
     364        if (!current_user_can('manage_options')) {
     365            wp_send_json_error([
     366                'message' => esc_html__('Unauthorized', 'setchat'),
     367            ], 403);
     368        }
     369
     370        $api_key = isset($_POST['api_key']) ? sanitize_text_field(wp_unslash($_POST['api_key'])) : '';
     371        if (empty($api_key)) {
     372            wp_send_json_error([
     373                'message' => esc_html__('No API key provided', 'setchat'),
     374            ], 400);
     375        }
     376
     377        $locale = get_option('setchat_locale', '');
     378        $response = wp_safe_remote_post(
     379            self::API_URL . '/api/widget/notifications/test',
     380            [
     381                'headers' => [
     382                    'x-api-key' => $api_key,
     383                    'Content-Type' => 'application/json',
     384                ],
     385                'timeout' => 12,
     386                'body' => wp_json_encode([
     387                    'locale' => $locale ?: get_locale(),
     388                ]),
     389            ]
     390        );
     391
     392        if (is_wp_error($response)) {
     393            wp_send_json_error([
     394                'message' => sanitize_text_field($response->get_error_message()),
     395            ], 500);
     396        }
     397
     398        $code = wp_remote_retrieve_response_code($response);
     399        $body = json_decode(wp_remote_retrieve_body($response), true);
     400        if ($code >= 200 && $code < 300) {
     401            $email_triggered = !empty($body['emailTriggered']);
     402            $teams_triggered = !empty($body['teamsTriggered']);
     403            $tested_at = current_time('mysql');
     404            update_option('setchat_last_notification_test', [
     405                'testedAt' => $tested_at,
     406                'emailTriggered' => $email_triggered,
     407                'teamsTriggered' => $teams_triggered,
     408            ], false);
     409
     410            wp_send_json_success([
     411                'emailTriggered' => $email_triggered,
     412                'teamsTriggered' => $teams_triggered,
     413                'testedAt' => $tested_at,
     414            ]);
     415        }
     416
     417        $message_raw = is_array($body) && isset($body['message'])
     418            ? $body['message']
     419            : __('Notification test failed', 'setchat');
     420        $message = sanitize_text_field((string) $message_raw);
     421        wp_send_json_error(['message' => $message], $code > 0 ? $code : 500);
     422    }
     423
     424    public function ajax_track_event() {
     425        check_ajax_referer('setchat_test_connection', 'nonce');
     426        if (!current_user_can('manage_options')) {
     427            wp_send_json_error(['message' => esc_html__('Unauthorized', 'setchat')], 403);
     428        }
     429        $api_key = isset($_POST['api_key']) ? sanitize_text_field(wp_unslash($_POST['api_key'])) : '';
     430        $event = isset($_POST['event']) ? sanitize_text_field(wp_unslash($_POST['event'])) : '';
     431        $metadata_raw = isset($_POST['metadata'])
     432            ? sanitize_textarea_field(wp_unslash($_POST['metadata']))
     433            : '';
     434        $metadata = [];
     435        if (is_string($metadata_raw) && $metadata_raw !== '') {
     436            $decoded = json_decode($metadata_raw, true);
     437            if (is_array($decoded)) {
     438                $metadata = $decoded;
     439            }
     440        }
     441        if ($api_key === '' || $event === '') {
     442            wp_send_json_error(['message' => esc_html__('Bad request', 'setchat')], 400);
     443        }
     444
     445        $response = wp_safe_remote_post(
     446            self::API_URL . '/api/widget/analytics/event',
     447            [
     448                'headers' => [
     449                    'x-api-key' => $api_key,
     450                    'Content-Type' => 'application/json',
     451                ],
     452                'timeout' => 8,
     453                'body' => wp_json_encode([
     454                    'event' => $event,
     455                    'source' => 'wordpress_plugin',
     456                    'metadata' => $metadata,
     457                ]),
     458            ]
     459        );
     460        if (is_wp_error($response)) {
     461            wp_send_json_error(['message' => sanitize_text_field($response->get_error_message())], 500);
     462        }
     463        $code = wp_remote_retrieve_response_code($response);
     464        if ($code >= 200 && $code < 300) {
     465            wp_send_json_success(['ok' => true]);
     466        }
     467        wp_send_json_error(['message' => esc_html__('Analytics event failed', 'setchat')], $code > 0 ? $code : 500);
    235468    }
    236469
     
    285518        $locale       = get_option('setchat_locale', '');
    286519        $position     = get_option('setchat_position', 'bottom-right');
     520        $primary_color   = get_option('setchat_primary_color', '');
     521        $secondary_color = get_option('setchat_secondary_color', '');
     522        $accent_color    = get_option('setchat_accent_color', '');
    287523        $enabled      = get_option('setchat_enabled', true);
    288524        $preview_mode = get_option('setchat_preview_mode', false);
     
    329565                                    <?php esc_html_e('Test connection', 'setchat'); ?>
    330566                                </button>
     567                                <button type="button" id="setchat-test-notification-btn" class="button button-secondary">
     568                                    <?php esc_html_e('Test notification', 'setchat'); ?>
     569                                </button>
    331570                            </div>
    332571                            <div id="setchat-test-result" class="setchat-test-result" style="display:none;"></div>
     572                            <p id="setchat-last-notification-test" class="description" style="margin-top:8px;"></p>
     573                            <div id="setchat-checklist" class="setchat-checklist" style="display:none;">
     574                                <div class="setchat-checklist-title"><?php esc_html_e('Activation checklist', 'setchat'); ?></div>
     575                                <div class="setchat-checklist-item setchat-status-pending" id="setchat-checklist-api-key">
     576                                    <span class="setchat-checklist-label"><?php esc_html_e('API key works', 'setchat'); ?></span>
     577                                    <span class="setchat-checklist-state" id="setchat-checklist-api-key-state"><?php esc_html_e('Pending', 'setchat'); ?></span>
     578                                </div>
     579                                <div class="setchat-checklist-item setchat-status-pending" id="setchat-checklist-widget-config">
     580                                    <span class="setchat-checklist-label"><?php esc_html_e('Widget config loaded', 'setchat'); ?></span>
     581                                    <span class="setchat-checklist-state" id="setchat-checklist-widget-config-state"><?php esc_html_e('Pending', 'setchat'); ?></span>
     582                                </div>
     583                                <div class="setchat-checklist-item setchat-status-pending" id="setchat-checklist-site">
     584                                    <span class="setchat-checklist-label"><?php esc_html_e('Site configured', 'setchat'); ?></span>
     585                                    <span class="setchat-checklist-state" id="setchat-checklist-site-state"><?php esc_html_e('Pending', 'setchat'); ?></span>
     586                                </div>
     587                                <div class="setchat-checklist-item setchat-status-pending" id="setchat-checklist-live-test">
     588                                    <span class="setchat-checklist-label"><?php esc_html_e('Live test detected', 'setchat'); ?></span>
     589                                    <span class="setchat-checklist-state" id="setchat-checklist-live-test-state"><?php esc_html_e('Pending', 'setchat'); ?></span>
     590                                </div>
     591                                <div class="setchat-checklist-item setchat-status-pending" id="setchat-checklist-notifications">
     592                                    <span class="setchat-checklist-label"><?php esc_html_e('Notifications ready', 'setchat'); ?></span>
     593                                    <span class="setchat-checklist-state" id="setchat-checklist-notifications-state"><?php esc_html_e('Pending', 'setchat'); ?></span>
     594                                </div>
     595
     596                                <div class="setchat-checklist-item setchat-status-pending" id="setchat-checklist-done">
     597                                    <span class="setchat-checklist-label"><?php esc_html_e('Ready for conversion', 'setchat'); ?></span>
     598                                    <span class="setchat-checklist-state" id="setchat-checklist-done-state"><?php esc_html_e('Pending', 'setchat'); ?></span>
     599                                </div>
     600
     601                                <div class="setchat-checklist-cta">
     602                                    <a class="button button-secondary" href="#" id="setchat-cta-faq" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Configure FAQ/KB', 'setchat'); ?></a>
     603                                    <a class="button button-secondary" href="#" id="setchat-cta-flows" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Create first flow', 'setchat'); ?></a>
     604                                    <a class="button button-secondary" href="#" id="setchat-cta-sites" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Configure sites', 'setchat'); ?></a>
     605                                    <a class="button button-secondary" href="#" id="setchat-cta-livetest" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Run live test', 'setchat'); ?></a>
     606                                    <a class="button button-secondary" href="#" id="setchat-cta-notifications" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Configure notifications', 'setchat'); ?></a>
     607                                </div>
     608                            </div>
    333609                            <p class="description">
    334610                                <?php
     
    363639                                <option value="bottom-left" <?php selected($position, 'bottom-left'); ?>><?php esc_html_e('Bottom left', 'setchat'); ?></option>
    364640                            </select>
     641                        </td>
     642                    </tr>
     643                </table>
     644
     645                <!-- Widget colors -->
     646                <h2><?php esc_html_e('Widget colors', 'setchat'); ?></h2>
     647                <table class="form-table" role="presentation">
     648                    <tr>
     649                        <th scope="row"><label for="setchat_primary_color"><?php esc_html_e('Primary color', 'setchat'); ?></label></th>
     650                        <td>
     651                            <input type="text" id="setchat_primary_color" name="setchat_primary_color" value="<?php echo esc_attr($primary_color); ?>" class="regular-text code" placeholder="#1B4332" />
     652                            <p class="description"><?php esc_html_e('Optional. Hex value (#RGB or #RRGGBB).', 'setchat'); ?></p>
     653                        </td>
     654                    </tr>
     655                    <tr>
     656                        <th scope="row"><label for="setchat_secondary_color"><?php esc_html_e('Secondary color', 'setchat'); ?></label></th>
     657                        <td>
     658                            <input type="text" id="setchat_secondary_color" name="setchat_secondary_color" value="<?php echo esc_attr($secondary_color); ?>" class="regular-text code" placeholder="#2D6A4F" />
     659                            <p class="description"><?php esc_html_e('Optional. Hex value (#RGB or #RRGGBB).', 'setchat'); ?></p>
     660                        </td>
     661                    </tr>
     662                    <tr>
     663                        <th scope="row"><label for="setchat_accent_color"><?php esc_html_e('Accent color', 'setchat'); ?></label></th>
     664                        <td>
     665                            <input type="text" id="setchat_accent_color" name="setchat_accent_color" value="<?php echo esc_attr($accent_color); ?>" class="regular-text code" placeholder="#52B788" />
     666                            <p class="description"><?php esc_html_e('Optional. Hex value (#RGB or #RRGGBB).', 'setchat'); ?></p>
    365667                        </td>
    366668                    </tr>
     
    567869        $locale   = get_option('setchat_locale', '');
    568870        $position = get_option('setchat_position', 'bottom-right');
     871        $primary_color   = get_option('setchat_primary_color', '');
     872        $secondary_color = get_option('setchat_secondary_color', '');
     873        $accent_color    = get_option('setchat_accent_color', '');
    569874
    570875        wp_enqueue_script('setchat-widget', self::WIDGET_URL, [], self::VERSION, [
     
    583888            $this->script_data['data-position'] = $position;
    584889        }
     890        if (!empty($primary_color)) {
     891            $this->script_data['data-primary-color'] = $primary_color;
     892        }
     893        if (!empty($secondary_color)) {
     894            $this->script_data['data-secondary-color'] = $secondary_color;
     895        }
     896        if (!empty($accent_color)) {
     897            $this->script_data['data-accent-color'] = $accent_color;
     898        }
    585899
    586900        $visitor      = $this->get_visitor_data();
     
    610924            'class' => '',
    611925        ], $atts, 'setchat');
    612 
    613         if (empty(get_option('setchat_api_key', ''))) {
    614             return '';
    615         }
     926        return $this->render_open_button((string) $atts['text'], (string) ($atts['class'] ?? ''));
     927    }
     928
     929    private function render_open_button(string $text, string $className) {
     930        if (empty(get_option('setchat_api_key', ''))) return '';
    616931
    617932        $classes = 'setchat-open-btn';
    618         if (!empty($atts['class'])) {
    619             $classes .= ' ' . esc_attr($atts['class']);
     933        if (!empty($className)) {
     934            $classes .= ' ' . esc_attr($className);
    620935        }
    621936
     
    623938            '<button type="button" class="%s" onclick="window.dispatchEvent(new CustomEvent(\'setchat:open\'))">%s</button>',
    624939            esc_attr($classes),
    625             esc_html($atts['text'])
     940            esc_html($text)
    626941        );
     942    }
     943
     944    public function register_gutenberg_block() {
     945        if (!function_exists('register_block_type')) return;
     946
     947        register_block_type('setchat/chat', [
     948            'editor_script' => 'setchat-gutenberg-block',
     949            'attributes' => [
     950                'text' => [
     951                    'type' => 'string',
     952                    'default' => __('Chat with us', 'setchat'),
     953                ],
     954                'className' => [
     955                    'type' => 'string',
     956                    'default' => '',
     957                ],
     958            ],
     959            'render_callback' => [$this, 'gutenberg_render_callback'],
     960        ]);
     961    }
     962
     963    public function enqueue_gutenberg_editor_assets() {
     964        // Editor-only script that defines the block `edit()` UI.
     965        wp_register_script(
     966            'setchat-gutenberg-block',
     967            plugin_dir_url(__FILE__) . 'assets/block.js',
     968            ['wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n'],
     969            self::VERSION,
     970            true
     971        );
     972        wp_enqueue_script('setchat-gutenberg-block');
     973    }
     974
     975    public function gutenberg_render_callback($attributes, $content, $block) {
     976        $text = isset($attributes['text']) ? (string) $attributes['text'] : __('Chat with us', 'setchat');
     977        $className = isset($attributes['className']) ? (string) $attributes['className'] : '';
     978        return $this->render_open_button($text, $className);
    627979    }
    628980
Note: See TracChangeset for help on using the changeset viewer.