- Improvements to EntitlementsDomain & Services - Prechecks in Document domain - Add audit information to LicenseUsage
108 lines
3.8 KiB
Python
108 lines
3.8 KiB
Python
"""UI Manager for handling all UI-related operations."""
|
|
from html import escape
|
|
from typing import Dict, Any, Optional, Generator
|
|
from flask import render_template, Flask
|
|
from datetime import datetime as dt
|
|
|
|
|
|
class UIManager:
|
|
"""Handles all UI-related operations and updates."""
|
|
def init_app(self, app: Flask) -> None:
|
|
pass
|
|
|
|
@staticmethod
|
|
def render_specialist_form(specialist_id: int, specialist: Dict[str, Any], config: Dict[str, Any]) -> str:
|
|
"""Render the specialist form."""
|
|
return render_template(
|
|
'specialist_form_chat.html',
|
|
specialist_id=specialist_id,
|
|
specialist=specialist,
|
|
config=config
|
|
)
|
|
|
|
@staticmethod
|
|
def render_message_exchange(query: str, task_id: str) -> str:
|
|
"""Render the message exchange between user and AI."""
|
|
return render_template(
|
|
'partials/message_exchange.html',
|
|
query=query,
|
|
task_id=task_id
|
|
)
|
|
|
|
@staticmethod
|
|
def render_error(error_message: str) -> str:
|
|
"""Render an error message."""
|
|
return f"""
|
|
<div class="alert alert-danger">Error: {error_message}</div>
|
|
"""
|
|
|
|
@staticmethod
|
|
def update_status_bar(message: str, message_type: str = 'info') -> str:
|
|
"""Generate HTML to update the status bar using HTMX out-of-band swaps."""
|
|
safe_message = escape(message)
|
|
current_time = dt.now().strftime('%H:%M:%S')
|
|
|
|
# Add a new status message to the status messages container
|
|
status_message_html = f'''
|
|
<div class="status-message {message_type}" hx-swap-oob="beforeend:#statusMessages">
|
|
[{current_time}] {safe_message}
|
|
</div>
|
|
'''
|
|
|
|
# Update the current status display
|
|
current_status_html = f'''
|
|
<span id="currentStatus" hx-swap-oob="innerHTML">
|
|
{safe_message}
|
|
</span>
|
|
'''
|
|
|
|
# Combine all updates with explicit scroll command
|
|
return status_message_html + current_status_html + '''
|
|
<script hx-swap-oob="beforeend:#statusMessages">
|
|
document.getElementById('consoleOutput').scrollTop = document.getElementById('consoleOutput').scrollHeight;
|
|
</script>
|
|
'''
|
|
|
|
@staticmethod
|
|
def update_processing_status(message: str, state_type: str = 'ready') -> str:
|
|
"""Generate HTML to update the processing status indicator."""
|
|
return f"""
|
|
<span id="processingStatus" hx-swap-oob="innerHTML" class="badge bg-{state_type}">
|
|
{message}
|
|
</span>
|
|
<script>
|
|
if (window.processingStatus) {{
|
|
window.processingStatus.updateStatus("{message}", "{state_type}");
|
|
}}
|
|
</script>
|
|
"""
|
|
|
|
@staticmethod
|
|
def update_ai_response(task_id: str, message: str, is_error: bool = False) -> str:
|
|
"""Generate HTML to update an AI response message."""
|
|
style = 'background-color: var(--bs-danger);' if is_error else ''
|
|
return f"""
|
|
<div id="response-{task_id}" hx-swap-oob="innerHTML">
|
|
<div class="message-bubble ai-message" style="{style}">{message}</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Scroll to bottom
|
|
document.getElementById('messageHistory').scrollTop =
|
|
document.getElementById('messageHistory').scrollHeight;
|
|
</script>
|
|
"""
|
|
|
|
@staticmethod
|
|
def create_typing_indicator(task_id: str) -> str:
|
|
"""Generate HTML for a typing indicator."""
|
|
return f"""
|
|
<div id="response-{task_id}" hx-swap-oob="innerHTML">
|
|
<div class="message-bubble ai-message">
|
|
<div class="typing-indicator">
|
|
<span></span><span></span><span></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
"""
|