- Wordpress improvements - Multi-language support
- Styling of the administrative interface in line with askeveai.com website
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
--algorithm-color-llm: #800080; /* Purple for RAG_LLM */
|
||||
|
||||
/*--font-family: 'Arial, sans-serif'; !* Default font family *!*/
|
||||
--font-family: 'ui-sans-serif, -apple-system, system-ui, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica, Apple Color Emoji, Arial, Segoe UI Emoji, Segoe UI Symbol';
|
||||
--font-family: 'Segoe UI, Roboto, Cantarell, Noto Sans, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol';
|
||||
--font-color: #e9e9e9; /* Default font color */
|
||||
--user-message-font-color: #e9e9e9; /* User message font color */
|
||||
--bot-message-font-color: #e9e9e9; /* Bot message font color */
|
||||
@@ -91,7 +91,7 @@
|
||||
.chat-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 99vh;
|
||||
height: 75vh;
|
||||
/*max-height: 100vh;*/
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
@@ -103,6 +103,13 @@
|
||||
color: var(--font-color); /* Apply the default font color */
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
font-size: 0.7em;
|
||||
text-align: right;
|
||||
padding: 5px 20px 5px 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.messages-area {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
@@ -115,6 +122,7 @@
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
border-radius: 15px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
@@ -150,21 +158,50 @@
|
||||
}
|
||||
|
||||
.question-area {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: var(--user-message-bg);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.question-area input {
|
||||
.language-select-container {
|
||||
width: 100%;
|
||||
margin-bottom: 10px; /* Spacing between the dropdown and the textarea */
|
||||
}
|
||||
|
||||
.language-select {
|
||||
width: 100%;
|
||||
margin-bottom: 5px; /* Space between the dropdown and the send button */
|
||||
padding: 8px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid var(--input-border);
|
||||
background-color: var(--input-bg);
|
||||
color: var(--input-text-color);
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.question-area textarea {
|
||||
flex: 1;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
border-radius: 15px;
|
||||
margin-right: 10px;
|
||||
background-color: var(--input-bg); /* Apply input background color */
|
||||
border: 1px solid var(--input-border); /* Apply input border color */
|
||||
color: var(--input-text-color); /* Apply input text color */
|
||||
background-color: var(--input-bg);
|
||||
border: 1px solid var(--input-border);
|
||||
color: var(--input-text-color);
|
||||
font-family: var(--font-family); /* Apply the default font family */
|
||||
font-size: 1rem;
|
||||
resize: vertical;
|
||||
min-height: 60px;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
margin-right: 10px; /* Space between textarea and right-side container */
|
||||
}
|
||||
|
||||
.right-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.question-area button {
|
||||
@@ -176,8 +213,9 @@
|
||||
|
||||
/* Styles for the send icon */
|
||||
.send-icon {
|
||||
font-size: 24px; /* Size of the icon */
|
||||
color: var(--button-color); /* Color of the icon */
|
||||
font-size: 24px;
|
||||
color: var(--button-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.send-icon.disabled {
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
Plugin Name: EveAI Chat Widget
|
||||
Plugin URI: https://askeveai.com/
|
||||
Description: Integrates the EveAI chat interface into your WordPress site.
|
||||
Version: 1.2
|
||||
Version: 1.3.20
|
||||
Author: Josako, Pieter Laroy
|
||||
Author URI: https://askeveai.com/about/
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
// Enqueue necessary scripts and styles
|
||||
@@ -28,6 +26,7 @@ function eveai_chat_shortcode($atts) {
|
||||
$api_key = esc_js($options['api_key']);
|
||||
$domain = esc_js($options['domain']);
|
||||
$language = esc_js($options['language']);
|
||||
$supported_languages = esc_js($options['supported_languages']);
|
||||
|
||||
// Generate a unique ID for this instance of the chat widget
|
||||
$chat_id = 'chat-container-' . uniqid();
|
||||
@@ -39,7 +38,8 @@ function eveai_chat_shortcode($atts) {
|
||||
'$tenant_id',
|
||||
'$api_key',
|
||||
'$domain',
|
||||
'$language'
|
||||
'$language',
|
||||
'$supported_languages'
|
||||
);
|
||||
eveAI.initializeChat('$chat_id');
|
||||
});
|
||||
@@ -81,6 +81,7 @@ function eveai_chat_register_settings() {
|
||||
add_settings_field('eveai_chat_api_key', 'API Key', 'eveai_chat_api_key_input', 'eveai-chat-settings', 'eveai_chat_main');
|
||||
add_settings_field('eveai_chat_domain', 'Domain', 'eveai_chat_domain_input', 'eveai-chat-settings', 'eveai_chat_main');
|
||||
add_settings_field('eveai_chat_language', 'Default Language', 'eveai_chat_language_input', 'eveai-chat-settings', 'eveai_chat_main');
|
||||
add_settings_field('eveai_chat_supported_languages', 'Supported Languages', 'eveai_chat_supported_languages_input', 'eveai-chat-settings', 'eveai_chat_main');
|
||||
}
|
||||
add_action('admin_init', 'eveai_chat_register_settings');
|
||||
|
||||
@@ -108,11 +109,20 @@ function eveai_chat_language_input() {
|
||||
echo "<input id='eveai_chat_language' name='eveai_chat_options[language]' type='text' value='" . esc_attr($options['language']) . "' />";
|
||||
}
|
||||
|
||||
function eveai_chat_supported_languages_input() {
|
||||
$options = get_option('eveai_chat_options');
|
||||
$supported_languages = isset($options['supported_languages']) ? $options['supported_languages'] : 'en,fr,de,es';
|
||||
echo "<input id='eveai_chat_supported_languages' name='eveai_chat_options[supported_languages]' type='text' value='" . esc_attr($supported_languages) . "' />";
|
||||
echo "<p class='description'>Enter comma-separated language codes (e.g., en,fr,de,es)</p>";
|
||||
}
|
||||
|
||||
|
||||
function eveai_chat_options_validate($input) {
|
||||
$new_input = array();
|
||||
$new_input['tenant_id'] = sanitize_text_field($input['tenant_id']);
|
||||
$new_input['api_key'] = sanitize_text_field($input['api_key']);
|
||||
$new_input['domain'] = esc_url_raw($input['domain']);
|
||||
$new_input['language'] = sanitize_text_field($input['language']);
|
||||
$new_input['supported_languages'] = sanitize_text_field($input['supported_languages']);
|
||||
return $new_input;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
class EveAIChatWidget extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['tenant-id', 'api-key', 'domain', 'language'];
|
||||
return ['tenant-id', 'api-key', 'domain', 'language', 'languages'];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@@ -12,6 +12,7 @@ class EveAIChatWidget extends HTMLElement {
|
||||
this.heartbeatInterval = null;
|
||||
this.idleTime = 0; // in milliseconds
|
||||
this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds
|
||||
this.languages = []
|
||||
console.log('EveAIChatWidget constructor called');
|
||||
}
|
||||
|
||||
@@ -19,15 +20,17 @@ class EveAIChatWidget extends HTMLElement {
|
||||
console.log('connectedCallback called');
|
||||
this.innerHTML = this.getTemplate();
|
||||
this.messagesArea = this.querySelector('.messages-area');
|
||||
this.questionInput = this.querySelector('.question-area input');
|
||||
this.questionInput = this.querySelector('.question-area textarea');
|
||||
this.sendButton = this.querySelector('.send-icon');
|
||||
this.languageSelect = this.querySelector('.language-select');
|
||||
this.statusLine = this.querySelector('.status-line');
|
||||
this.statusMessage = this.querySelector('.status-message');
|
||||
this.connectionStatusIcon = this.querySelector('.connection-status-icon');
|
||||
|
||||
this.sendButton.addEventListener('click', () => this.handleSendMessage());
|
||||
this.questionInput.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault(); // Prevent adding a new line
|
||||
this.handleSendMessage();
|
||||
}
|
||||
});
|
||||
@@ -38,6 +41,30 @@ class EveAIChatWidget extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
populateLanguageDropdown() {
|
||||
// Clear existing options
|
||||
this.languageSelect.innerHTML = '';
|
||||
console.log(`languages for options: ${this.languages}`)
|
||||
|
||||
// Populate with new options
|
||||
this.languages.forEach(lang => {
|
||||
const option = document.createElement('option');
|
||||
option.value = lang;
|
||||
option.textContent = lang.toUpperCase();
|
||||
if (lang === this.currentLanguage) {
|
||||
option.selected = true;
|
||||
}
|
||||
console.log(`Adding option for language: ${lang}`)
|
||||
this.languageSelect.appendChild(option);
|
||||
});
|
||||
|
||||
// Add event listener for language change
|
||||
this.languageSelect.addEventListener('change', (e) => {
|
||||
this.currentLanguage = e.target.value;
|
||||
// You might want to emit an event or update the backend about the language change
|
||||
});
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
console.log(`attributeChangedCallback called: ${name} changed from ${oldValue} to ${newValue}`);
|
||||
this.updateAttributes();
|
||||
@@ -45,6 +72,9 @@ class EveAIChatWidget extends HTMLElement {
|
||||
if (this.areAllAttributesSet() && !this.socket) {
|
||||
console.log('All attributes set in attributeChangedCallback, initializing socket');
|
||||
this.attributesSet = true;
|
||||
console.log('All attributes are set, populating language dropdown');
|
||||
this.populateLanguageDropdown();
|
||||
console.log('All attributes are set, initializing socket')
|
||||
this.initializeSocket();
|
||||
}
|
||||
}
|
||||
@@ -54,11 +84,16 @@ class EveAIChatWidget extends HTMLElement {
|
||||
this.apiKey = this.getAttribute('api-key');
|
||||
this.domain = this.getAttribute('domain');
|
||||
this.language = this.getAttribute('language');
|
||||
const languageAttr = this.getAttribute('languages');
|
||||
this.languages = languageAttr ? languageAttr.split(',') : [];
|
||||
this.currentLanguage = this.language;
|
||||
console.log('Updated attributes:', {
|
||||
tenantId: this.tenantId,
|
||||
apiKey: this.apiKey,
|
||||
domain: this.domain,
|
||||
language: this.language
|
||||
language: this.language,
|
||||
currentLanguage: this.currentLanguage,
|
||||
languages: this.languages
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,13 +102,34 @@ class EveAIChatWidget extends HTMLElement {
|
||||
const apiKey = this.getAttribute('api-key');
|
||||
const domain = this.getAttribute('domain');
|
||||
const language = this.getAttribute('language');
|
||||
const languages = this.getAttribute('languages');
|
||||
console.log('Checking if all attributes are set:', {
|
||||
tenantId,
|
||||
apiKey,
|
||||
domain,
|
||||
language
|
||||
language,
|
||||
languages
|
||||
});
|
||||
return tenantId && apiKey && domain && language;
|
||||
return tenantId && apiKey && domain && language && languages;
|
||||
}
|
||||
|
||||
createLanguageDropdown() {
|
||||
const select = document.createElement('select');
|
||||
select.id = 'languageSelect';
|
||||
this.languages.forEach(lang => {
|
||||
const option = document.createElement('option');
|
||||
option.value = lang;
|
||||
option.textContent = lang.toUpperCase();
|
||||
if (lang === this.currentLanguage) {
|
||||
option.selected = true;
|
||||
}
|
||||
select.appendChild(option);
|
||||
});
|
||||
select.addEventListener('change', (e) => {
|
||||
this.currentLanguage = e.target.value;
|
||||
// You might want to emit an event or update the backend about the language change
|
||||
});
|
||||
return select;
|
||||
}
|
||||
|
||||
initializeSocket() {
|
||||
@@ -81,15 +137,11 @@ class EveAIChatWidget extends HTMLElement {
|
||||
console.log('Socket already initialized');
|
||||
return;
|
||||
}
|
||||
if (!this.domain || this.domain === 'null') {
|
||||
console.error('Domain attribute is missing or invalid');
|
||||
this.setStatusMessage('EveAI Chat Widget needs further configuration by site administrator.');
|
||||
return;
|
||||
}
|
||||
console.log(`Initializing socket connection to ${this.domain}`);
|
||||
|
||||
console.log(`Initializing socket connection to Evie`);
|
||||
|
||||
// Ensure apiKey is passed in the query parameters
|
||||
this.socket = io(this.domain, {
|
||||
this.socket = io('https://evie.askeveai.com', {
|
||||
path: '/chat/socket.io/',
|
||||
transports: ['websocket', 'polling'],
|
||||
query: {
|
||||
@@ -104,7 +156,7 @@ class EveAIChatWidget extends HTMLElement {
|
||||
timeout: 20000 // Connection timeout
|
||||
});
|
||||
|
||||
console.log(`Finished initializing socket connection to ${this.domain}`);
|
||||
console.log(`Finished initializing socket connection to Evie`);
|
||||
|
||||
this.socket.on('connect', (data) => {
|
||||
console.log('Socket connected OK');
|
||||
@@ -243,9 +295,13 @@ class EveAIChatWidget extends HTMLElement {
|
||||
return `
|
||||
<div class="chat-container">
|
||||
<div class="messages-area"></div>
|
||||
<div class="disclaimer">Evie can make mistakes. Please double-check responses.</div>
|
||||
<div class="question-area">
|
||||
<input type="text" placeholder="Type your message here..." />
|
||||
<i class="material-icons send-icon outlined">send</i>
|
||||
<textarea placeholder="Type your message here..." rows="3"></textarea>
|
||||
<div class="right-side">
|
||||
<select class="language-select"></select>
|
||||
<i class="material-icons send-icon outlined">send</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="status-line">
|
||||
<i class="material-icons connection-status-icon">link_off</i>
|
||||
@@ -370,12 +426,15 @@ toggleFeedback(thumbsUp, thumbsDown, feedback, interactionId) {
|
||||
console.error('JWT token is not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedLanguage = this.languageSelect.value;
|
||||
|
||||
console.log('Sending message to backend');
|
||||
this.socket.emit('user_message', {
|
||||
tenantId: this.tenantId,
|
||||
token: this.jwtToken,
|
||||
message,
|
||||
language: this.language,
|
||||
language: selectedLanguage,
|
||||
timezone: this.userTimezone
|
||||
});
|
||||
this.setStatusMessage('Processing started ...')
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// static/js/eveai-sdk.js
|
||||
class EveAI {
|
||||
constructor(tenantId, apiKey, domain, language) {
|
||||
constructor(tenantId, apiKey, domain, language, languages) {
|
||||
this.tenantId = tenantId;
|
||||
this.apiKey = apiKey;
|
||||
this.domain = domain;
|
||||
this.language = language;
|
||||
this.languages = languages;
|
||||
|
||||
console.log('EveAI constructor:', { tenantId, apiKey, domain });
|
||||
console.log('EveAI constructor:', { tenantId, apiKey, domain, language, languages });
|
||||
}
|
||||
|
||||
initializeChat(containerId) {
|
||||
@@ -19,6 +20,7 @@ class EveAI {
|
||||
chatWidget.setAttribute('api-key', this.apiKey);
|
||||
chatWidget.setAttribute('domain', this.domain);
|
||||
chatWidget.setAttribute('language', this.language);
|
||||
chatWidget.setAttribute('languages', this.languages);
|
||||
});
|
||||
} else {
|
||||
console.error('Container not found');
|
||||
|
||||
@@ -3,7 +3,7 @@ Contributors: Josako
|
||||
Tags: chat, ai
|
||||
Requires at least: 5.0
|
||||
Tested up to: 5.9
|
||||
Stable tag: 1.2
|
||||
Stable tag: 1.3.0
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
@@ -27,17 +27,32 @@ Contact your EveAI service provider to obtain your Tenant ID, API Key, and Domai
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.2 =
|
||||
= 1.3.3 - =
|
||||
* ensure all attributes (also height and supportedLanguages) are set before initializing the socket
|
||||
* Bugfixing
|
||||
|
||||
= 1.3.2 =
|
||||
* Correct supportedLanguages to be an Array
|
||||
|
||||
= 1.3.1 =
|
||||
* Correct evie domain
|
||||
|
||||
= 1.3.0 =
|
||||
* Enable user to select language
|
||||
* Make Question area multi-line
|
||||
* Enable height to be set in shortcode
|
||||
|
||||
= 1.2.0 =
|
||||
* Create shortcodes
|
||||
|
||||
= 1.1 =
|
||||
= 1.1.0 =
|
||||
* Added configurable settings
|
||||
* Improved security with server-side API key handling
|
||||
|
||||
= 1.0 =
|
||||
= 1.0.0 =
|
||||
* Initial release
|
||||
|
||||
== Upgrade Notice ==
|
||||
|
||||
= 1.1 =
|
||||
= 1.1.0 =
|
||||
This version adds configurable settings and improves security. Please update your EveAI credentials after upgrading.
|
||||
Reference in New Issue
Block a user