diff --git a/common/services/interaction/specialist_services.py b/common/services/interaction/specialist_services.py index cc2d549..fda1f30 100644 --- a/common/services/interaction/specialist_services.py +++ b/common/services/interaction/specialist_services.py @@ -223,10 +223,11 @@ class SpecialistServices: @staticmethod def get_specialist_system_field(specialist_id, config_name, system_name): + """Get the value of a system field in a specialist's configuration. Returns the actual value, or None.""" specialist = Specialist.query.get(specialist_id) if not specialist: raise ValueError(f"Specialist with ID {specialist_id} not found") - config = cache_manager.specialists_config_cache.get_config(specialist.type, specialist.version) + config = cache_manager.specialists_config_cache.get_config(specialist.type, specialist.type_version) if not config: raise ValueError(f"No configuration found for {specialist.type} version {specialist.version}") potential_field = config.get(config_name, None) diff --git a/common/utils/chat_utils.py b/common/utils/chat_utils.py index 65912aa..10783db 100644 --- a/common/utils/chat_utils.py +++ b/common/utils/chat_utils.py @@ -5,11 +5,11 @@ Utility functions for chat customization. def get_default_chat_customisation(tenant_customisation=None): """ Get chat customization options with default values for missing options. - + Args: tenant_customization (dict, optional): The tenant's customization options. Defaults to None. - + Returns: dict: A dictionary containing all customization options with default values for any missing options. @@ -21,22 +21,25 @@ def get_default_chat_customisation(tenant_customisation=None): 'background_color': '#ffffff', 'text_color': '#212529', 'sidebar_color': '#f8f9fa', - 'logo_url': None, - 'sidebar_text': None, + 'sidebar_background': '#2c3e50', + 'gradient_start_color': '#f5f7fa', + 'gradient_end_color': '#c3cfe2', + 'markdown_background_color': 'transparent', + 'markdown_text_color': '#ffffff', + 'sidebar_markdown': '', 'welcome_message': 'Hello! How can I help you today?', - 'team_info': [] } - + # If no tenant customization is provided, return the defaults if tenant_customisation is None: return default_customisation - + # Start with the default customization customisation = default_customisation.copy() - + # Update with tenant customization for key, value in tenant_customisation.items(): if key in customisation: customisation[key] = value - - return customisation \ No newline at end of file + + return customisation diff --git a/config/customisations/globals/CHAT_CLIENT_CUSTOMISATION/1.0.0.yaml b/config/customisations/globals/CHAT_CLIENT_CUSTOMISATION/1.0.0.yaml index 9ee6310..2f08133 100644 --- a/config/customisations/globals/CHAT_CLIENT_CUSTOMISATION/1.0.0.yaml +++ b/config/customisations/globals/CHAT_CLIENT_CUSTOMISATION/1.0.0.yaml @@ -26,9 +26,34 @@ configuration: description: "Sidebar Color" type: "color" required: false - "sidebar_text": - name: "Sidebar Text" - description: "Text to be shown in the sidebar" + "sidebar_background": + name: "Sidebar Background" + description: "Sidebar Background Color" + type: "color" + required: false + "markdown_background_color": + name: "Markdown Background" + description: "Markdown Background Color" + type: "color" + required: false + "markdown_text_color": + name: "Markdown Text" + description: "Markdown Text Color" + type: "color" + required: false + "gradient_start_color": + name: "Gradient Start Color" + description: "Start Color for the gradient in the Chat Area" + type: "color" + required: false + "gradient_end_color": + name: "Gradient End Color" + description: "End Color for the gradient in the Chat Area" + type: "color" + required: false + "sidebar_markdown": + name: "Sidebar Markdown" + description: "Sidebar Markdown-formatted Text" type: "text" required: false "welcome_message": diff --git a/eveai_app/views/basic_forms.py b/eveai_app/views/basic_forms.py index 47ec19f..7fdc3c3 100644 --- a/eveai_app/views/basic_forms.py +++ b/eveai_app/views/basic_forms.py @@ -1,4 +1,4 @@ -from flask import session +from flask import session, current_app from flask_security import current_user from flask_wtf import FlaskForm from wtforms import StringField, SelectField @@ -36,7 +36,7 @@ class SessionDefaultsForm(FlaskForm): else: self.partner_name.data = "" self.default_language.choices = [(lang, lang.lower()) for lang in - session.get('tenant').get('allowed_languages')] + current_app.config['SUPPORTED_LANGUAGES']] self.default_language.data = session.get('default_language') # Get a new session for catalog queries diff --git a/eveai_app/views/document_forms.py b/eveai_app/views/document_forms.py index 9b2cfaf..8f01459 100644 --- a/eveai_app/views/document_forms.py +++ b/eveai_app/views/document_forms.py @@ -190,7 +190,7 @@ class AddDocumentForm(DynamicFormBase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.language.choices = [(language, language) for language in - session.get('tenant').get('allowed_languages')] + current_app.config['SUPPORTED_LANGUAGES']] if not self.language.data: self.language.data = session.get('tenant').get('default_language') @@ -210,7 +210,7 @@ class AddURLForm(DynamicFormBase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.language.choices = [(language, language) for language in - session.get('tenant').get('allowed_languages')] + current_app.config['SUPPORTED_LANGUAGES']] if not self.language.data: self.language.data = session.get('tenant').get('default_language') diff --git a/eveai_app/views/interaction_forms.py b/eveai_app/views/interaction_forms.py index 2e48a0e..67193d4 100644 --- a/eveai_app/views/interaction_forms.py +++ b/eveai_app/views/interaction_forms.py @@ -182,11 +182,6 @@ class EditSpecialistMagicLinkForm(DynamicFormBase): tenant_makes = TenantMake.query.all() self.tenant_make_id.choices = [(0, 'None')] + [(make.id, make.name) for make in tenant_makes] - # If the form has a tenant_make_id that's not zero, set the tenant_make_name - if hasattr(self, 'tenant_make_id') and self.tenant_make_id.data and self.tenant_make_id.data > 0: - tenant_make = TenantMake.query.get(self.tenant_make_id.data) - if tenant_make: - self.tenant_make_name.data = tenant_make.name diff --git a/eveai_app/views/interaction_views.py b/eveai_app/views/interaction_views.py index cb3754c..3d53b19 100644 --- a/eveai_app/views/interaction_views.py +++ b/eveai_app/views/interaction_views.py @@ -694,10 +694,6 @@ def specialist_magic_link(): # Populate fields individually instead of using populate_obj form.populate_obj(new_specialist_magic_link) - # Handle the tenant_make_id special case (0 = None) - if form.tenant_make_id.data == 0: - new_specialist_magic_link.tenant_make_id = None - set_logging_information(new_specialist_magic_link, dt.now(tz.utc)) # Create 'public' SpecialistMagicLinkTenant @@ -706,7 +702,7 @@ def specialist_magic_link(): new_spec_ml_tenant.tenant_id = tenant_id # Define the make valid for this magic link - make_id = SpecialistServices.get_specialist_system_field(new_specialist_magic_link.id, + make_id = SpecialistServices.get_specialist_system_field(new_specialist_magic_link.specialist_id, "make", "tenant_make") if make_id: new_spec_ml_tenant.tenant_make_id = make_id diff --git a/eveai_app/views/user_forms.py b/eveai_app/views/user_forms.py index 593939b..b364f36 100644 --- a/eveai_app/views/user_forms.py +++ b/eveai_app/views/user_forms.py @@ -177,13 +177,17 @@ class EditTenantProjectForm(FlaskForm): def validate_make_name(form, field): - # Controleer of een TenantMake met deze naam al bestaat + # Check if tenant_make already exists in the database existing_make = TenantMake.query.filter_by(name=field.data).first() - # Als er een bestaande make is gevonden en we zijn niet in edit mode, - # of als we wel in edit mode zijn maar het is een ander record (andere id) - if existing_make and (not hasattr(form, 'id') or form.id.data != existing_make.id): - raise ValidationError(f'A Make with name "{field.data}" already exists. Choose another name.') + if existing_make: + current_app.logger.debug(f'Existing make: {existing_make.id}') + current_app.logger.debug(f'Form has id: {hasattr(form, 'id')}') + if hasattr(form, 'id'): + current_app.logger.debug(f'Form has id: {form.id.data}') + if existing_make: + if not hasattr(form, 'id') or form.id.data != existing_make.id: + raise ValidationError(f'A Make with name "{field.data}" already exists. Choose another name.') class TenantMakeForm(DynamicFormBase): diff --git a/eveai_app/views/user_views.py b/eveai_app/views/user_views.py index 31d4060..47855ce 100644 --- a/eveai_app/views/user_views.py +++ b/eveai_app/views/user_views.py @@ -12,7 +12,7 @@ from common.utils.dynamic_field_utils import create_default_config_from_type_con from common.utils.security_utils import send_confirmation_email, send_reset_email from config.type_defs.service_types import SERVICE_TYPES from .user_forms import TenantForm, CreateUserForm, EditUserForm, TenantDomainForm, TenantSelectionForm, \ - TenantProjectForm, EditTenantProjectForm, TenantMakeForm, EditTenantForm + TenantProjectForm, EditTenantProjectForm, TenantMakeForm, EditTenantForm, EditTenantMakeForm from common.utils.database import Database from common.utils.view_assistants import prepare_table_for_macro, form_validation_failed from common.utils.simple_encryption import generate_api_key @@ -701,7 +701,7 @@ def edit_tenant_make(tenant_make_id): tenant_make = TenantMake.query.get_or_404(tenant_make_id) # Create form instance with the tenant make - form = TenantMakeForm(request.form, obj=tenant_make) + form = EditTenantMakeForm(request.form, obj=tenant_make) customisation_config = cache_manager.customisations_config_cache.get_config("CHAT_CLIENT_CUSTOMISATION") form.add_dynamic_fields("configuration", customisation_config, tenant_make.chat_customisation_options) @@ -755,6 +755,8 @@ def handle_tenant_make_selection(): # Update session data if necessary if 'tenant' in session: session['tenant'] = tenant.to_dict() + return None + return None except SQLAlchemyError as e: db.session.rollback() flash(f'Failed to update default tenant make. Error: {str(e)}', 'danger') @@ -762,6 +764,9 @@ def handle_tenant_make_selection(): return redirect(prefixed_url_for('user_bp.tenant_makes')) + return None + + def reset_uniquifier(user): security.datastore.set_uniquifier(user) db.session.add(user) diff --git a/eveai_chat_client/templates/base.html b/eveai_chat_client/templates/base.html index e8877a1..1a1441e 100644 --- a/eveai_chat_client/templates/base.html +++ b/eveai_chat_client/templates/base.html @@ -4,10 +4,16 @@