- Wordpress improvements - Multi-language support
- Styling of the administrative interface in line with askeveai.com website
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
<script src="https://kit.fontawesome.com/42d5adcbca.js" crossorigin="anonymous"></script>
|
<script src="https://kit.fontawesome.com/42d5adcbca.js" crossorigin="anonymous"></script>
|
||||||
<!-- Material Icons -->
|
<!-- Material Icons -->
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
|
||||||
<!-- CSS Files -->
|
<!-- CSS Files -->
|
||||||
<link id="pagestyle" href="{{url_for('static', filename='assets/css/material-kit-pro.css')}}" rel="stylesheet" />
|
<link id="pagestyle" href="{{url_for('static', filename='assets/css/material-kit-pro.css')}}" rel="stylesheet" />
|
||||||
<link id="pagestyle" href="{{url_for('static', filename='assets/css/eveai.css')}}" rel="stylesheet" />
|
<link id="pagestyle" href="{{url_for('static', filename='assets/css/eveai.css')}}" rel="stylesheet" />
|
||||||
|
|||||||
@@ -220,21 +220,33 @@
|
|||||||
{% macro render_pagination(pagination, endpoint) %}
|
{% macro render_pagination(pagination, endpoint) %}
|
||||||
<nav aria-label="Page navigation">
|
<nav aria-label="Page navigation">
|
||||||
<ul class="pagination">
|
<ul class="pagination">
|
||||||
|
<!-- Previous Button -->
|
||||||
<li class="page-item {{ 'disabled' if not pagination.has_prev }}">
|
<li class="page-item {{ 'disabled' if not pagination.has_prev }}">
|
||||||
<a class="page-link" href="{{ url_for(endpoint, page=pagination.prev_num) if pagination.has_prev else 'javascript:;' }}" tabindex="-1">
|
<a class="page-link" href="{{ url_for(endpoint, page=pagination.prev_num) if pagination.has_prev else 'javascript:;' }}" tabindex="-1">
|
||||||
<i class="fa fa-angle-left"></i>
|
<span class="material-symbols-outlined">keyboard_double_arrow_left</span>
|
||||||
<span class="sr-only">Previous</span>
|
{# <span class="sr-only">Previous</span>#}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<!-- Page Number Buttons -->
|
||||||
{% for page in pagination.iter_pages(left_edge=1, left_current=2, right_current=3, right_edge=1) %}
|
{% for page in pagination.iter_pages(left_edge=1, left_current=2, right_current=3, right_edge=1) %}
|
||||||
<li class="page-item {{ 'active' if page == pagination.page }}">
|
<li class="page-item {{ 'active' if page == pagination.page }}">
|
||||||
<a class="page-link" href="{{ url_for(endpoint, page=page) }}">{{ page }} {% if page == pagination.page %}<span class="sr-only">(current)</span>{% endif %}</a>
|
<a class="page-link" href="{{ url_for(endpoint, page=page) }}">
|
||||||
|
{% if page == pagination.page %}
|
||||||
|
<span class="material-symbols-outlined">target</span>
|
||||||
|
{# <span class="sr-only">(current)</span>#}
|
||||||
|
{% else %}
|
||||||
|
{{ page }}
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
<!-- Next Button -->
|
||||||
<li class="page-item {{ 'disabled' if not pagination.has_next }}">
|
<li class="page-item {{ 'disabled' if not pagination.has_next }}">
|
||||||
<a class="page-link" href="{{ url_for(endpoint, page=pagination.next_num) if pagination.has_next else 'javascript:;' }}">
|
<a class="page-link" href="{{ url_for(endpoint, page=pagination.next_num) if pagination.has_next else 'javascript:;' }}">
|
||||||
<i class="fa fa-angle-right"></i>
|
<span class="material-symbols-outlined">keyboard_double_arrow_right</span>
|
||||||
<span class="sr-only">Next</span>
|
{# <span class="sr-only">Next</span>#}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<li class="nav-item dropdown dropdown-hover mx-2">
|
<li class="nav-item dropdown dropdown-hover mx-2">
|
||||||
<a role="button" class="nav-link ps-2 d-flex cursor-pointer align-items-center" id="{{ title | replace(' ', '') }}" data-bs-toggle="dropdown" aria-expanded="false">
|
<a role="button" class="nav-link ps-2 d-flex cursor-pointer align-items-center" id="{{ title | replace(' ', '') }}" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
{% if icon %}
|
{% if icon %}
|
||||||
<i class="material-icons opacity-6 me-2 text-md">{{ icon }}</i>
|
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;">{{ icon }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ title }}
|
{{ title }}
|
||||||
<img src="{{ url_for('static', filename='assets/img/down-arrow-dark.svg') }}" alt="down-arrow" class="arrow ms-2">
|
<img src="{{ url_for('static', filename='assets/img/down-arrow-dark.svg') }}" alt="down-arrow" class="arrow ms-2">
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
<div class="collapse navbar-collapse w-100 pt-3 pb-2 py-lg-0" id="navigation">
|
<div class="collapse navbar-collapse w-100 pt-3 pb-2 py-lg-0" id="navigation">
|
||||||
<ul class="navbar-nav navbar-nav-hover mx-auto">
|
<ul class="navbar-nav navbar-nav-hover mx-auto">
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
{{ dropdown('Tenant Configuration', 'contacts', [
|
{{ dropdown('Tenant Configuration', 'source_environment', [
|
||||||
{'name': 'Tenant List', 'url': '/user/select_tenant', 'roles': ['Super User']},
|
{'name': 'Tenant List', 'url': '/user/select_tenant', 'roles': ['Super User']},
|
||||||
{'name': 'Tenant Registration', 'url': '/user/tenant', 'roles': ['Super User']},
|
{'name': 'Tenant Registration', 'url': '/user/tenant', 'roles': ['Super User']},
|
||||||
{'name': 'Tenant Overview', 'url': '/user/tenant_overview', 'roles': ['Super User', 'Tenant Admin']},
|
{'name': 'Tenant Overview', 'url': '/user/tenant_overview', 'roles': ['Super User', 'Tenant Admin']},
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
]) }}
|
]) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
{{ dropdown('Document Mgmt', 'contacts', [
|
{{ dropdown('Document Mgmt', 'note_stack', [
|
||||||
{'name': 'Add Document', 'url': '/document/add_document', 'roles': ['Super User', 'Tenant Admin']},
|
{'name': 'Add Document', 'url': '/document/add_document', 'roles': ['Super User', 'Tenant Admin']},
|
||||||
{'name': 'Add URL', 'url': '/document/add_url', 'roles': ['Super User', 'Tenant Admin']},
|
{'name': 'Add URL', 'url': '/document/add_url', 'roles': ['Super User', 'Tenant Admin']},
|
||||||
{'name': 'Add a list of URLs', 'url': '/document/add_urls', 'roles': ['Super User', 'Tenant Admin']},
|
{'name': 'Add a list of URLs', 'url': '/document/add_urls', 'roles': ['Super User', 'Tenant Admin']},
|
||||||
@@ -90,17 +90,17 @@
|
|||||||
]) }}
|
]) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
{{ dropdown('Interactions', 'contacts', [
|
{{ dropdown('Interactions', 'hub', [
|
||||||
{'name': 'Chat Sessions', 'url': '/interaction/chat_sessions', 'roles': ['Super User', 'Tenant Admin']},
|
{'name': 'Chat Sessions', 'url': '/interaction/chat_sessions', 'roles': ['Super User', 'Tenant Admin']},
|
||||||
]) }}
|
]) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
{{ dropdown(current_user.user_name, 'contacts', [
|
{{ dropdown(current_user.user_name, 'person', [
|
||||||
{'name': 'Session Defaults', 'url': '/session_defaults', 'roles': ['Super User', 'Tenant Admin']},
|
{'name': 'Session Defaults', 'url': '/session_defaults', 'roles': ['Super User', 'Tenant Admin']},
|
||||||
{'name': 'Logout', 'url': '/logout'}
|
{'name': 'Logout', 'url': '/logout'}
|
||||||
]) }}
|
]) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ dropdown('Account', 'contacts', [
|
{{ dropdown('Account', 'person', [
|
||||||
{'name': 'Login', 'url': '/login'}
|
{'name': 'Login', 'url': '/login'}
|
||||||
]) }}
|
]) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
--algorithm-color-llm: #800080; /* Purple for RAG_LLM */
|
--algorithm-color-llm: #800080; /* Purple for RAG_LLM */
|
||||||
|
|
||||||
/*--font-family: 'Arial, sans-serif'; !* Default font family *!*/
|
/*--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 */
|
--font-color: #e9e9e9; /* Default font color */
|
||||||
--user-message-font-color: #e9e9e9; /* User message font color */
|
--user-message-font-color: #e9e9e9; /* User message font color */
|
||||||
--bot-message-font-color: #e9e9e9; /* Bot message font color */
|
--bot-message-font-color: #e9e9e9; /* Bot message font color */
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
.chat-container {
|
.chat-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 99vh;
|
height: 75vh;
|
||||||
/*max-height: 100vh;*/
|
/*max-height: 100vh;*/
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
@@ -103,6 +103,13 @@
|
|||||||
color: var(--font-color); /* Apply the default font color */
|
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 {
|
.messages-area {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -115,6 +122,7 @@
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message.user {
|
.message.user {
|
||||||
@@ -150,21 +158,50 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.question-area {
|
.question-area {
|
||||||
padding: 10px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: var(--user-message-bg);
|
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;
|
flex: 1;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
margin-right: 10px;
|
background-color: var(--input-bg);
|
||||||
background-color: var(--input-bg); /* Apply input background color */
|
border: 1px solid var(--input-border);
|
||||||
border: 1px solid var(--input-border); /* Apply input border color */
|
color: var(--input-text-color);
|
||||||
color: var(--input-text-color); /* Apply 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 {
|
.question-area button {
|
||||||
@@ -176,8 +213,9 @@
|
|||||||
|
|
||||||
/* Styles for the send icon */
|
/* Styles for the send icon */
|
||||||
.send-icon {
|
.send-icon {
|
||||||
font-size: 24px; /* Size of the icon */
|
font-size: 24px;
|
||||||
color: var(--button-color); /* Color of the icon */
|
color: var(--button-color);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.send-icon.disabled {
|
.send-icon.disabled {
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
Plugin Name: EveAI Chat Widget
|
Plugin Name: EveAI Chat Widget
|
||||||
Plugin URI: https://askeveai.com/
|
Plugin URI: https://askeveai.com/
|
||||||
Description: Integrates the EveAI chat interface into your WordPress site.
|
Description: Integrates the EveAI chat interface into your WordPress site.
|
||||||
Version: 1.2
|
Version: 1.3.20
|
||||||
Author: Josako, Pieter Laroy
|
Author: Josako, Pieter Laroy
|
||||||
Author URI: https://askeveai.com/about/
|
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
|
// Enqueue necessary scripts and styles
|
||||||
@@ -28,6 +26,7 @@ function eveai_chat_shortcode($atts) {
|
|||||||
$api_key = esc_js($options['api_key']);
|
$api_key = esc_js($options['api_key']);
|
||||||
$domain = esc_js($options['domain']);
|
$domain = esc_js($options['domain']);
|
||||||
$language = esc_js($options['language']);
|
$language = esc_js($options['language']);
|
||||||
|
$supported_languages = esc_js($options['supported_languages']);
|
||||||
|
|
||||||
// Generate a unique ID for this instance of the chat widget
|
// Generate a unique ID for this instance of the chat widget
|
||||||
$chat_id = 'chat-container-' . uniqid();
|
$chat_id = 'chat-container-' . uniqid();
|
||||||
@@ -39,7 +38,8 @@ function eveai_chat_shortcode($atts) {
|
|||||||
'$tenant_id',
|
'$tenant_id',
|
||||||
'$api_key',
|
'$api_key',
|
||||||
'$domain',
|
'$domain',
|
||||||
'$language'
|
'$language',
|
||||||
|
'$supported_languages'
|
||||||
);
|
);
|
||||||
eveAI.initializeChat('$chat_id');
|
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_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_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_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');
|
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']) . "' />";
|
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) {
|
function eveai_chat_options_validate($input) {
|
||||||
$new_input = array();
|
$new_input = array();
|
||||||
$new_input['tenant_id'] = sanitize_text_field($input['tenant_id']);
|
$new_input['tenant_id'] = sanitize_text_field($input['tenant_id']);
|
||||||
$new_input['api_key'] = sanitize_text_field($input['api_key']);
|
$new_input['api_key'] = sanitize_text_field($input['api_key']);
|
||||||
$new_input['domain'] = esc_url_raw($input['domain']);
|
$new_input['domain'] = esc_url_raw($input['domain']);
|
||||||
$new_input['language'] = sanitize_text_field($input['language']);
|
$new_input['language'] = sanitize_text_field($input['language']);
|
||||||
|
$new_input['supported_languages'] = sanitize_text_field($input['supported_languages']);
|
||||||
return $new_input;
|
return $new_input;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
class EveAIChatWidget extends HTMLElement {
|
class EveAIChatWidget extends HTMLElement {
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return ['tenant-id', 'api-key', 'domain', 'language'];
|
return ['tenant-id', 'api-key', 'domain', 'language', 'languages'];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -12,6 +12,7 @@ class EveAIChatWidget extends HTMLElement {
|
|||||||
this.heartbeatInterval = null;
|
this.heartbeatInterval = null;
|
||||||
this.idleTime = 0; // in milliseconds
|
this.idleTime = 0; // in milliseconds
|
||||||
this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds
|
this.maxConnectionIdleTime = 1 * 60 * 60 * 1000; // 1 hours in milliseconds
|
||||||
|
this.languages = []
|
||||||
console.log('EveAIChatWidget constructor called');
|
console.log('EveAIChatWidget constructor called');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,15 +20,17 @@ class EveAIChatWidget extends HTMLElement {
|
|||||||
console.log('connectedCallback called');
|
console.log('connectedCallback called');
|
||||||
this.innerHTML = this.getTemplate();
|
this.innerHTML = this.getTemplate();
|
||||||
this.messagesArea = this.querySelector('.messages-area');
|
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.sendButton = this.querySelector('.send-icon');
|
||||||
|
this.languageSelect = this.querySelector('.language-select');
|
||||||
this.statusLine = this.querySelector('.status-line');
|
this.statusLine = this.querySelector('.status-line');
|
||||||
this.statusMessage = this.querySelector('.status-message');
|
this.statusMessage = this.querySelector('.status-message');
|
||||||
this.connectionStatusIcon = this.querySelector('.connection-status-icon');
|
this.connectionStatusIcon = this.querySelector('.connection-status-icon');
|
||||||
|
|
||||||
this.sendButton.addEventListener('click', () => this.handleSendMessage());
|
this.sendButton.addEventListener('click', () => this.handleSendMessage());
|
||||||
this.questionInput.addEventListener('keydown', (event) => {
|
this.questionInput.addEventListener('keydown', (event) => {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter' && !event.shiftKey) {
|
||||||
|
event.preventDefault(); // Prevent adding a new line
|
||||||
this.handleSendMessage();
|
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) {
|
attributeChangedCallback(name, oldValue, newValue) {
|
||||||
console.log(`attributeChangedCallback called: ${name} changed from ${oldValue} to ${newValue}`);
|
console.log(`attributeChangedCallback called: ${name} changed from ${oldValue} to ${newValue}`);
|
||||||
this.updateAttributes();
|
this.updateAttributes();
|
||||||
@@ -45,6 +72,9 @@ class EveAIChatWidget extends HTMLElement {
|
|||||||
if (this.areAllAttributesSet() && !this.socket) {
|
if (this.areAllAttributesSet() && !this.socket) {
|
||||||
console.log('All attributes set in attributeChangedCallback, initializing socket');
|
console.log('All attributes set in attributeChangedCallback, initializing socket');
|
||||||
this.attributesSet = true;
|
this.attributesSet = true;
|
||||||
|
console.log('All attributes are set, populating language dropdown');
|
||||||
|
this.populateLanguageDropdown();
|
||||||
|
console.log('All attributes are set, initializing socket')
|
||||||
this.initializeSocket();
|
this.initializeSocket();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,11 +84,16 @@ class EveAIChatWidget extends HTMLElement {
|
|||||||
this.apiKey = this.getAttribute('api-key');
|
this.apiKey = this.getAttribute('api-key');
|
||||||
this.domain = this.getAttribute('domain');
|
this.domain = this.getAttribute('domain');
|
||||||
this.language = this.getAttribute('language');
|
this.language = this.getAttribute('language');
|
||||||
|
const languageAttr = this.getAttribute('languages');
|
||||||
|
this.languages = languageAttr ? languageAttr.split(',') : [];
|
||||||
|
this.currentLanguage = this.language;
|
||||||
console.log('Updated attributes:', {
|
console.log('Updated attributes:', {
|
||||||
tenantId: this.tenantId,
|
tenantId: this.tenantId,
|
||||||
apiKey: this.apiKey,
|
apiKey: this.apiKey,
|
||||||
domain: this.domain,
|
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 apiKey = this.getAttribute('api-key');
|
||||||
const domain = this.getAttribute('domain');
|
const domain = this.getAttribute('domain');
|
||||||
const language = this.getAttribute('language');
|
const language = this.getAttribute('language');
|
||||||
|
const languages = this.getAttribute('languages');
|
||||||
console.log('Checking if all attributes are set:', {
|
console.log('Checking if all attributes are set:', {
|
||||||
tenantId,
|
tenantId,
|
||||||
apiKey,
|
apiKey,
|
||||||
domain,
|
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() {
|
initializeSocket() {
|
||||||
@@ -81,15 +137,11 @@ class EveAIChatWidget extends HTMLElement {
|
|||||||
console.log('Socket already initialized');
|
console.log('Socket already initialized');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.domain || this.domain === 'null') {
|
|
||||||
console.error('Domain attribute is missing or invalid');
|
console.log(`Initializing socket connection to Evie`);
|
||||||
this.setStatusMessage('EveAI Chat Widget needs further configuration by site administrator.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(`Initializing socket connection to ${this.domain}`);
|
|
||||||
|
|
||||||
// Ensure apiKey is passed in the query parameters
|
// Ensure apiKey is passed in the query parameters
|
||||||
this.socket = io(this.domain, {
|
this.socket = io('https://evie.askeveai.com', {
|
||||||
path: '/chat/socket.io/',
|
path: '/chat/socket.io/',
|
||||||
transports: ['websocket', 'polling'],
|
transports: ['websocket', 'polling'],
|
||||||
query: {
|
query: {
|
||||||
@@ -104,7 +156,7 @@ class EveAIChatWidget extends HTMLElement {
|
|||||||
timeout: 20000 // Connection timeout
|
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) => {
|
this.socket.on('connect', (data) => {
|
||||||
console.log('Socket connected OK');
|
console.log('Socket connected OK');
|
||||||
@@ -243,9 +295,13 @@ class EveAIChatWidget extends HTMLElement {
|
|||||||
return `
|
return `
|
||||||
<div class="chat-container">
|
<div class="chat-container">
|
||||||
<div class="messages-area"></div>
|
<div class="messages-area"></div>
|
||||||
|
<div class="disclaimer">Evie can make mistakes. Please double-check responses.</div>
|
||||||
<div class="question-area">
|
<div class="question-area">
|
||||||
<input type="text" placeholder="Type your message here..." />
|
<textarea placeholder="Type your message here..." rows="3"></textarea>
|
||||||
<i class="material-icons send-icon outlined">send</i>
|
<div class="right-side">
|
||||||
|
<select class="language-select"></select>
|
||||||
|
<i class="material-icons send-icon outlined">send</i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-line">
|
<div class="status-line">
|
||||||
<i class="material-icons connection-status-icon">link_off</i>
|
<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');
|
console.error('JWT token is not available');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectedLanguage = this.languageSelect.value;
|
||||||
|
|
||||||
console.log('Sending message to backend');
|
console.log('Sending message to backend');
|
||||||
this.socket.emit('user_message', {
|
this.socket.emit('user_message', {
|
||||||
tenantId: this.tenantId,
|
tenantId: this.tenantId,
|
||||||
token: this.jwtToken,
|
token: this.jwtToken,
|
||||||
message,
|
message,
|
||||||
language: this.language,
|
language: selectedLanguage,
|
||||||
timezone: this.userTimezone
|
timezone: this.userTimezone
|
||||||
});
|
});
|
||||||
this.setStatusMessage('Processing started ...')
|
this.setStatusMessage('Processing started ...')
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
// static/js/eveai-sdk.js
|
// static/js/eveai-sdk.js
|
||||||
class EveAI {
|
class EveAI {
|
||||||
constructor(tenantId, apiKey, domain, language) {
|
constructor(tenantId, apiKey, domain, language, languages) {
|
||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
this.apiKey = apiKey;
|
this.apiKey = apiKey;
|
||||||
this.domain = domain;
|
this.domain = domain;
|
||||||
this.language = language;
|
this.language = language;
|
||||||
|
this.languages = languages;
|
||||||
|
|
||||||
console.log('EveAI constructor:', { tenantId, apiKey, domain });
|
console.log('EveAI constructor:', { tenantId, apiKey, domain, language, languages });
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeChat(containerId) {
|
initializeChat(containerId) {
|
||||||
@@ -19,6 +20,7 @@ class EveAI {
|
|||||||
chatWidget.setAttribute('api-key', this.apiKey);
|
chatWidget.setAttribute('api-key', this.apiKey);
|
||||||
chatWidget.setAttribute('domain', this.domain);
|
chatWidget.setAttribute('domain', this.domain);
|
||||||
chatWidget.setAttribute('language', this.language);
|
chatWidget.setAttribute('language', this.language);
|
||||||
|
chatWidget.setAttribute('languages', this.languages);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error('Container not found');
|
console.error('Container not found');
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Contributors: Josako
|
|||||||
Tags: chat, ai
|
Tags: chat, ai
|
||||||
Requires at least: 5.0
|
Requires at least: 5.0
|
||||||
Tested up to: 5.9
|
Tested up to: 5.9
|
||||||
Stable tag: 1.2
|
Stable tag: 1.3.0
|
||||||
License: GPLv2 or later
|
License: GPLv2 or later
|
||||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
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 ==
|
== 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
|
* Create shortcodes
|
||||||
|
|
||||||
= 1.1 =
|
= 1.1.0 =
|
||||||
* Added configurable settings
|
* Added configurable settings
|
||||||
* Improved security with server-side API key handling
|
* Improved security with server-side API key handling
|
||||||
|
|
||||||
= 1.0 =
|
= 1.0.0 =
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
== Upgrade Notice ==
|
== Upgrade Notice ==
|
||||||
|
|
||||||
= 1.1 =
|
= 1.1.0 =
|
||||||
This version adds configurable settings and improves security. Please update your EveAI credentials after upgrading.
|
This version adds configurable settings and improves security. Please update your EveAI credentials after upgrading.
|
||||||
@@ -8,6 +8,405 @@
|
|||||||
--bs-danger: #9c2d66;
|
--bs-danger: #9c2d66;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Overriding the background gradient and text colors */
|
||||||
|
.bg-gradient-success {
|
||||||
|
background: linear-gradient(90deg, var(--bs-primary) 0%, var(--bs-secondary) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-success {
|
||||||
|
box-shadow: 0px 4px 20px 0px rgba(118, 89, 154, 0.5); /* Adjusting shadow color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-radius-lg {
|
||||||
|
border-radius: 1rem; /* Assuming you want to keep the large border-radius */
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-white {
|
||||||
|
color: #f8e1a9 !important; /* Adjust text to the EveAI success color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-sm {
|
||||||
|
font-size: 0.875rem; /* Adjust size if needed, keeping original */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Override for the link with text-success and text-gradient classes */
|
||||||
|
.text-success {
|
||||||
|
color: var(--bs-primary) !important; /* Use EveAI primary color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gradient {
|
||||||
|
background-image: linear-gradient(90deg, var(--bs-primary), var(--bs-secondary));
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-weight-bold {
|
||||||
|
font-weight: 700; /* Retain bold text */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navbar customization */
|
||||||
|
.navbar-light .navbar-brand {
|
||||||
|
color: var(--bs-primary) !important; /* Primary color for the brand text */
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-light .navbar-nav .nav-link {
|
||||||
|
color: var(--bs-secondary) !important; /* Secondary color for the nav links */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure consistent alignment for all dropdown icons */
|
||||||
|
.navbar-nav .nav-link i.material-icons {
|
||||||
|
font-size: 24px; /* Ensures all icons are the same size */
|
||||||
|
vertical-align: middle; /* Align icons vertically with text */
|
||||||
|
margin-right: 8px; /* Space between icon and text */
|
||||||
|
line-height: 1; /* Prevents misalignment due to line-height issues */
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav .nav-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center; /* Aligns icon and text vertically */
|
||||||
|
padding: 0; /* Remove any additional padding */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust the size and spacing of the material-symbols-outlined icons */
|
||||||
|
.navbar-nav .nav-link .material-symbols-outlined {
|
||||||
|
font-size: 20px; /* Adjust the icon size */
|
||||||
|
vertical-align: middle; /* Ensure vertical alignment with text */
|
||||||
|
margin-right: 8px; /* Add space between the icon and the text */
|
||||||
|
line-height: 1; /* Maintain alignment */
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-light .navbar-nav .nav-link:hover,
|
||||||
|
.navbar-light .navbar-nav .nav-link:focus {
|
||||||
|
color: var(--bs-primary) !important; /* Primary color on hover/focus */
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
background-color: var(--bs-light) !important; /* Adjust the background to a custom light color if needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.bg-gradient-primary {
|
||||||
|
background: linear-gradient(90deg, var(--bs-primary) 0%, var(--bs-secondary) 100%);
|
||||||
|
color: var(--bs-white) !important; /* Ensures text is readable on the gradient */
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler .navbar-toggler-bar {
|
||||||
|
background-color: var(--bs-secondary); /* Adjusts color of the toggler bars */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
background-color: var(--bs-light); /* Light background for dropdown */
|
||||||
|
border-radius: 0.375rem; /* Retains rounded corners */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
color: var(--bs-primary) !important; /* Primary color for dropdown items */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:hover,
|
||||||
|
.dropdown-item:focus {
|
||||||
|
background-color: var(--bs-secondary) !important; /* Secondary color for hover/focus background */
|
||||||
|
color: var(--bs-white) !important; /* White text on hover/focus */
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.bg-gradient-primary {
|
||||||
|
background: linear-gradient(90deg, var(--bs-primary) 0%, var(--bs-secondary) 100%);
|
||||||
|
color: var(--bs-white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Page header customization */
|
||||||
|
.page-header {
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
min-height: 25vh;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header .mask {
|
||||||
|
background: linear-gradient(90deg, var(--bs-primary), var(--bs-secondary)) !important; /* Gradient overlay */
|
||||||
|
opacity: 0.8; /* Adjust opacity to let the background image show through */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h1 {
|
||||||
|
color: var(--bs-success) !important; /* Use the success color for the header text */
|
||||||
|
margin-top: -1.5rem; /* Adjusted margin to align text properly */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header p.lead {
|
||||||
|
color: var(--bs-info) !important; /* Use the info color for the lead text */
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure consistent padding */
|
||||||
|
.page-header .container {
|
||||||
|
padding-top: 3rem;
|
||||||
|
padding-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header .col-lg-7 {
|
||||||
|
margin-top: -5rem; /* Adjust margin to improve vertical alignment */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card and table customization */
|
||||||
|
.card {
|
||||||
|
border: 1px solid var(--bs-secondary) !important; /* Secondary color for the card border */
|
||||||
|
border-radius: 0.5rem; /* Keeps the border-radius consistent */
|
||||||
|
box-shadow: 0 4px 8px rgba(118, 89, 154, 0.2); /* Soft shadow with primary color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
color: var(--bs-body-color) !important; /* Ensure the text color matches the theme */
|
||||||
|
background-color: var(--bs-light) !important; /* Light background color */
|
||||||
|
border-collapse: separate !important; /* Ensure borders do not collapse */
|
||||||
|
border-spacing: 0; /* Remove spacing between table cells */
|
||||||
|
border-radius: 0.375rem; /* Rounded corners */
|
||||||
|
overflow: hidden; /* Ensure the rounded corners apply to the entire table */
|
||||||
|
border: 1px solid var(--bs-secondary) !important; /* Apply border with secondary color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.table thead th {
|
||||||
|
color: var(--bs-info) !important; /* Info color for the table headers */
|
||||||
|
background-color: var(--bs-light) !important; /* Background for table headers */
|
||||||
|
border-bottom: 1px solid var(--bs-secondary) !important; /* Secondary color for the header bottom border */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensures corners are colored */
|
||||||
|
.table thead th:first-child {
|
||||||
|
border-top-left-radius: 0.375rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table thead th:last-child {
|
||||||
|
border-top-right-radius: 0.375rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:last-child td:first-child {
|
||||||
|
border-bottom-left-radius: 0.375rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:last-child td:last-child {
|
||||||
|
border-bottom-right-radius: 0.375rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr {
|
||||||
|
border-top: 1px solid var(--bs-gray-300) !important; /* Subtle border between rows */
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:hover {
|
||||||
|
background-color: var(--bs-secondary) !important; /* Secondary color on row hover */
|
||||||
|
color: var(--bs-white) !important; /* White text on hover */
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:hover a,
|
||||||
|
.table tbody tr:hover p,
|
||||||
|
.table tbody tr:hover td {
|
||||||
|
color: var(--bs-white) !important; /* Ensure all text, links, and paragraphs change to white */
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:hover .text-xs {
|
||||||
|
color: var(--bs-white) !important; /* Ensure the smaller text also changes to white */
|
||||||
|
}
|
||||||
|
|
||||||
|
.table .text-xs {
|
||||||
|
color: var(--bs-body-color) !important; /* Consistent text color in the table cells */
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="radio"] {
|
||||||
|
accent-color: var(--bs-primary); /* Primary color for radio buttons */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons customization */
|
||||||
|
.btn-primary {
|
||||||
|
background-color: var(--bs-primary) !important;
|
||||||
|
border-color: var(--bs-primary) !important;
|
||||||
|
color: var(--bs-white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: var(--bs-secondary) !important;
|
||||||
|
border-color: var(--bs-secondary) !important;
|
||||||
|
color: var(--bs-white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust the form group margin */
|
||||||
|
.form-group {
|
||||||
|
margin-top: 1.5rem; /* Adjust for better spacing */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card footer customization */
|
||||||
|
.card-footer {
|
||||||
|
/*background-color: var(--bs-light) !important; !* Light background for the footer *!*/
|
||||||
|
padding-top: 1rem; /* Adjust padding for consistent spacing */
|
||||||
|
padding-bottom: 1rem; /* Adjust padding for consistent spacing */
|
||||||
|
/*border-top: 1px solid var(--bs-secondary) !important; !* Border with secondary color *!*/
|
||||||
|
padding-left: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-footer .pagination {
|
||||||
|
padding-left: 0 !important; /* Remove extra padding */
|
||||||
|
padding-right: 0 !important; /* Remove extra padding */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pagination customization */
|
||||||
|
.pagination {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 0;
|
||||||
|
list-style: none;
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
margin-left: 0 !important;
|
||||||
|
margin-right: 0 !important;
|
||||||
|
padding-left: 0 !important; /* Add some padding inside the pagination */
|
||||||
|
padding-right: 0 !important; /* Add some padding inside the pagination */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination .page-item {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-item.disabled .page-link {
|
||||||
|
color: var(--bs-gray-500) !important; /* Disabled state color */
|
||||||
|
background-color: var(--bs-gray-200) !important; /* Disabled state background */
|
||||||
|
border-color: var(--bs-gray-300) !important; /* Disabled state border */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-item.active .page-link {
|
||||||
|
z-index: 1;
|
||||||
|
color: var(--bs-white) !important; /* Active page color */
|
||||||
|
background-color: var(--bs-primary) !important; /* Active page background */
|
||||||
|
border-color: var(--bs-primary) !important; /* Active page border */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-item .page-link {
|
||||||
|
border-radius: 50% !important; /* Ensure circular buttons */
|
||||||
|
margin: 0 5px; /* Add some spacing between buttons */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-link {
|
||||||
|
color: var(--bs-primary) !important; /* Default link color */
|
||||||
|
background-color: var(--bs-light) !important; /* Light background for links */
|
||||||
|
border: 1px solid var(--bs-secondary) !important; /* Border with secondary color */
|
||||||
|
border-radius: 0.375rem; /* Rounded corners */
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
margin: 0 0.25rem; /* Adjust margin for spacing */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-link:hover {
|
||||||
|
color: var(--bs-white) !important; /* Hover state text color */
|
||||||
|
background-color: var(--bs-secondary) !important; /* Hover state background */
|
||||||
|
border-color: var(--bs-secondary) !important; /* Hover state border */
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-link i.fa {
|
||||||
|
margin-right: 0.25rem; /* Add spacing between icon and text */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Align text centrally */
|
||||||
|
.text-center {
|
||||||
|
text-align: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form and Input Fields */
|
||||||
|
.form-group label.form-label {
|
||||||
|
color: var(--bs-secondary) !important; /* Secondary color for labels */
|
||||||
|
font-weight: 500; /* Slightly bolder labels */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group:last-of-type {
|
||||||
|
margin-bottom: 2rem; /* Adjust this value to control spacing */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
background-color: var(--bs-light) !important; /* Light background for input fields */
|
||||||
|
border-color: var(--bs-secondary) !important; /* Secondary color for borders */
|
||||||
|
color: var(--bs-body-color) !important; /* Text color consistent with the theme */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control:disabled {
|
||||||
|
background-color: var(--bs-gray-100) !important; /* Gray background for disabled fields */
|
||||||
|
color: var(--bs-gray-600) !important; /* Dimmed text color for disabled fields */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check-input:checked {
|
||||||
|
background-color: var(--bs-primary) !important; /* Primary color for checked checkboxes */
|
||||||
|
border-color: var(--bs-primary) !important; /* Primary color for checkbox border */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-check-label {
|
||||||
|
color: var(--bs-body-color) !important; /* Consistent text color for check labels */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabs Navigation */
|
||||||
|
.nav-pills .nav-link {
|
||||||
|
color: var(--bs-primary) !important; /* Primary color for inactive tab text */
|
||||||
|
border-radius: 0.375rem !important; /* Rounded corners for tabs */
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease; /* Smooth transitions */
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-pills .nav-link.active {
|
||||||
|
background-color: var(--bs-primary) !important; /* Primary background for active tab */
|
||||||
|
color: var(--bs-white) !important; /* White text for active tab */
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-pills .nav-link:hover {
|
||||||
|
background-color: var(--bs-secondary) !important; /* Secondary background on hover */
|
||||||
|
color: var(--bs-white) !important; /* White text on hover */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabs Content */
|
||||||
|
.tab-pane {
|
||||||
|
padding-top: 1rem; /* Consistent padding inside tabs */
|
||||||
|
}
|
||||||
|
|
||||||
|
.moving-tab {
|
||||||
|
background-color: var(--bs-primary) !important; /* Primary color for the moving tab indicator */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: var(--bs-secondary) !important;
|
||||||
|
border-color: var(--bs-secondary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#copy-message {
|
||||||
|
color: var(--bs-success) !important; /* Success color for the copy message */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Danger Button Styling */
|
||||||
|
.btn-danger {
|
||||||
|
background-color: var(--bs-danger) !important; /* Use the danger color from the EveAI theme */
|
||||||
|
border-color: var(--bs-danger) !important;
|
||||||
|
color: var(--bs-white) !important; /* Ensure text is white for readability */
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease; /* Smooth transition on hover */
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger:hover {
|
||||||
|
background-color: darken(var(--bs-danger), 10%) !important; /* Darken the background on hover */
|
||||||
|
border-color: darken(var(--bs-danger), 10%) !important; /* Darken the border on hover */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success Alert Styling */
|
||||||
|
.alert-success {
|
||||||
|
background-color: var(--bs-success) !important; /* EveAI success background color */
|
||||||
|
color: var(--bs-dark) !important; /* Dark color for the text for better readability */
|
||||||
|
border-color: var(--bs-success) !important; /* Matching border color */
|
||||||
|
border-radius: 0.375rem; /* Rounded corners for the alert box */
|
||||||
|
padding: 1rem; /* Consistent padding */
|
||||||
|
box-shadow: 0px 4px 10px rgba(118, 89, 154, 0.2); /* Soft shadow for some depth */
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-success .alert-heading {
|
||||||
|
color: var(--bs-dark) !important; /* Ensure the heading stands out */
|
||||||
|
font-weight: 600; /* Slightly bolder heading */
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-success p {
|
||||||
|
margin-bottom: 0; /* Remove extra margin from paragraphs inside alerts */
|
||||||
|
}
|
||||||
|
|
||||||
.form-control {
|
.form-control {
|
||||||
border: 1px solid #d2d6da;
|
border: 1px solid #d2d6da;
|
||||||
padding: 0.625rem 0.75rem;
|
padding: 0.625rem 0.75rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user