- RQC output of TRAICIE_SELECTION_SPECIALIST to EveAIDataCapsule

This commit is contained in:
Josako
2025-07-25 04:27:19 +02:00
parent 8a85b4540f
commit ba523a95c5
11 changed files with 338 additions and 5 deletions

View File

@@ -0,0 +1,111 @@
{% extends "base.html" %}
{% block title %}View Data Capsule{% endblock %}
{% block content_title %}Data Capsule Details{% endblock %}
{% block content_description %}View information about this EvAI Data Capsule and its content.{% endblock %}
{% block content %}
<div class="container mt-5">
<!-- Basic Information Section -->
<h4 class="mb-3">Basis Informatie</h4>
<table class="table table-bordered">
<tr>
<th>ID</th>
<td>{{ data_capsule.id }}</td>
</tr>
<tr>
<th>Type</th>
<td>{{ data_capsule.type }}</td>
</tr>
<tr>
<th>Type Version</th>
<td>{{ data_capsule.type_version }}</td>
</tr>
<tr>
<th>Created At</th>
<td>{{ data_capsule.created_at }}</td>
</tr>
<tr>
<th>Chat Session ID</th>
<td>
<a href="{{ url_for('interaction_bp.view_chat_session', chat_session_id=data_capsule.chat_session_id) }}">
{{ data_capsule.chat_session_id }}
</a>
</td>
</tr>
</table>
<!-- Chat Session Information Section -->
<h4 class="mb-3 mt-4">Chat Sessie Informatie</h4>
<table class="table table-bordered">
<tr>
<th>Session ID</th>
<td>{{ chat_session.session_id }}</td>
</tr>
<tr>
<th>Session Start</th>
<td>{{ chat_session.session_start }}</td>
</tr>
<tr>
<th>Session End</th>
<td>{{ chat_session.session_end }}</td>
</tr>
</table>
<!-- Configuration Data Section -->
{% if data_capsule.configuration %}
<h4 class="mb-3 mt-4">Configuratie</h4>
<div id="configuration-viewer" class="json-viewer" style="height: 300px; width: 100%; border: 1px solid #dee2e6;"></div>
<div id="configuration-viewer-data" class="d-none">{{ data_capsule.configuration | tojson(indent=2) }}</div>
{% endif %}
<!-- Capsule Data Section -->
{% if data_capsule.data %}
<h4 class="mb-3 mt-4">Data</h4>
<div id="data-viewer" class="json-viewer" style="height: 300px; width: 100%; border: 1px solid #dee2e6;"></div>
<div id="data-viewer-data" class="d-none">{{ data_capsule.data | tojson(indent=2) }}</div>
{% endif %}
<!-- Navigation Buttons -->
<div class="mt-5 mb-4">
<a href="{{ url_for('interaction_bp.eveai_data_capsules') }}" class="btn btn-primary">
<i class="fas fa-arrow-left"></i> Back to Data Capsules
</a>
<a href="{{ url_for('interaction_bp.view_chat_session', chat_session_id=data_capsule.chat_session_id) }}" class="btn btn-secondary">
<i class="fas fa-comments"></i> View Chat Session
</a>
</div>
</div>
<!-- Initialize JSON Editor for the data fields -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize Configuration JSON Editor if available
if (document.getElementById('configuration-viewer')) {
const configurationData = JSON.parse(document.getElementById('configuration-viewer-data').textContent);
const configurationViewer = new JSONEditor(document.getElementById('configuration-viewer'), {
mode: 'view',
mainMenuBar: false,
navigationBar: false,
statusBar: false,
readOnly: true,
onChangeJSON: function() { /* read only */ }
}, configurationData);
}
// Initialize Data JSON Editor if available
if (document.getElementById('data-viewer')) {
const capsuleData = JSON.parse(document.getElementById('data-viewer-data').textContent);
const dataViewer = new JSONEditor(document.getElementById('data-viewer'), {
mode: 'view',
mainMenuBar: false,
navigationBar: false,
statusBar: false,
readOnly: true,
onChangeJSON: function() { /* read only */ }
}, capsuleData);
}
});
</script>
{% endblock %}

View File

@@ -109,6 +109,7 @@
{'name': 'Specialists', 'url': '/interaction/specialists', 'roles': ['Super User', 'Partner Admin', 'Tenant Admin']},
{'name': 'Specialist Magic Links', 'url': '/interaction/specialist_magic_links', 'roles': ['Super User', 'Partner Admin', 'Tenant Admin']},
{'name': 'Assets', 'url': '/interaction/assets', 'roles': ['Super User', 'Partner Admin', 'Tenant Admin']},
{'name': 'Data Capsules', 'url': '/interaction//eveai_data_capsules', 'roles': ['Super User', 'Partner Admin', 'Tenant Admin']},
{'name': 'Chat Sessions', 'url': '/interaction/chat_sessions', 'roles': ['Super User', 'Partner Admin', 'Tenant Admin']},
]) }}
{% endif %}

View File

@@ -15,7 +15,7 @@ from werkzeug.utils import secure_filename
from common.models.document import Embedding, DocumentVersion, Retriever
from common.models.interaction import (ChatSession, Interaction, InteractionEmbedding, Specialist, SpecialistRetriever,
EveAIAgent, EveAITask, EveAITool, EveAIAsset, SpecialistMagicLink)
EveAIAgent, EveAITask, EveAITool, EveAIAsset, SpecialistMagicLink, EveAIDataCapsule)
from common.extensions import db, cache_manager
from common.models.user import SpecialistMagicLinkTenant
@@ -32,7 +32,8 @@ from .interaction_forms import (SpecialistForm, EditSpecialistForm, EditEveAIAge
SpecialistMagicLinkForm, EditSpecialistMagicLinkForm)
from eveai_app.views.list_views.interaction_list_views import (get_specialists_list_view, get_assets_list_view,
get_magic_links_list_view, get_chat_sessions_list_view)
get_magic_links_list_view, get_chat_sessions_list_view,
get_eveai_data_capsules_list_view)
from eveai_app.views.list_views.list_view_utils import render_list_view
interaction_bp = Blueprint('interaction_bp', __name__, url_prefix='/interaction')
@@ -747,12 +748,42 @@ def handle_specialist_magic_link_selection():
# Routes for Asset Management ---------------------------------------------------------------------
@interaction_bp.route('/eveai_data_capsules', methods=['GET', 'POST'])
@roles_accepted('Super User', 'Partner Admin', 'Tenant Admin')
def eveai_data_capsules():
# Get configuration and render the list view
config = get_eveai_data_capsules_list_view()
return render_list_view('list_view.html', **config)
@interaction_bp.route('/assets', methods=['GET', 'POST'])
def assets():
config = get_assets_list_view()
return render_list_view('list_view.html', **config)
@interaction_bp.route('/handle_data_capsule_selection', methods=['POST'])
@roles_accepted('Super User', 'Partner Admin', 'Tenant Admin')
def handle_data_capsule_selection():
data_capsule_identification = request.form['selected_row']
capsule_id = ast.literal_eval(data_capsule_identification).get('value')
action = request.form['action']
# Get the data capsule
data_capsule = EveAIDataCapsule.query.get_or_404(capsule_id)
match action:
case 'view_data_capsule':
# For now, we'll just redirect to view_data_capsule
return redirect(prefixed_url_for('interaction_bp.view_data_capsule', data_capsule_id=capsule_id))
case 'view_chat_session':
# Redirect to the chat session
return redirect(prefixed_url_for('interaction_bp.view_chat_session', chat_session_id=data_capsule.chat_session_id))
# Default redirect back to the data capsules list
return redirect(prefixed_url_for('interaction_bp.eveai_data_capsules'))
@interaction_bp.route('/handle_asset_selection', methods=['POST'])
def handle_asset_selection():
action = request.form.get('action')
@@ -765,6 +796,20 @@ def handle_asset_selection():
return redirect(prefixed_url_for('interaction_bp.assets'))
@interaction_bp.route('/view_data_capsule/<int:data_capsule_id>', methods=['GET'])
@roles_accepted('Super User', 'Partner Admin', 'Tenant Admin')
def view_data_capsule(data_capsule_id):
# Get the data capsule
data_capsule = EveAIDataCapsule.query.get_or_404(data_capsule_id)
# Get the related chat session
chat_session = ChatSession.query.get_or_404(data_capsule.chat_session_id)
return render_template('interaction/view_data_capsule.html',
data_capsule=data_capsule,
chat_session=chat_session)
@interaction_bp.route('/edit_asset/<int:asset_id>', methods=['GET', 'POST'])
def edit_asset(asset_id):
asset = EveAIAsset.query.get_or_404(asset_id)

View File

@@ -4,7 +4,7 @@ from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import desc
import ast
from common.models.interaction import Specialist, SpecialistMagicLink, ChatSession
from common.models.interaction import Specialist, SpecialistMagicLink, ChatSession, EveAIDataCapsule
from common.utils.nginx_utils import prefixed_url_for
from eveai_app.views.list_views.list_view_utils import render_list_view
@@ -196,3 +196,51 @@ def get_chat_sessions_list_view():
'table_height': 800
}
def get_eveai_data_capsules_list_view():
"""Generate the EvAI Data Capsules list view configuration"""
# Get all data capsules ordered by creation date (descending)
data_capsules_query = EveAIDataCapsule.query.order_by(desc(EveAIDataCapsule.created_at))
all_data_capsules = data_capsules_query.all()
# Prepare data for Tabulator
data = []
for capsule in all_data_capsules:
data.append({
'id': capsule.id,
'chat_session_id': capsule.chat_session_id,
'type': capsule.type,
'type_version': capsule.type_version,
'created_at': capsule.created_at.strftime('%Y-%m-%d %H:%M:%S') if capsule.created_at else ''
})
# Column definitions
columns = [
{'title': 'ID', 'field': 'id', 'width': 80},
{'title': 'Chat Session ID', 'field': 'chat_session_id'},
{'title': 'Type', 'field': 'type'},
{'title': 'Type Version', 'field': 'type_version'},
{'title': 'Created At', 'field': 'created_at'}
]
# Action definitions
actions = [
{'value': 'view_data_capsule', 'text': 'View Details', 'class': 'btn-primary', 'requiresSelection': True},
{'value': 'view_chat_session', 'text': 'View Chat Session', 'class': 'btn-secondary', 'requiresSelection': True}
]
# Initial sort configuration
initial_sort = [{'column': 'created_at', 'dir': 'desc'}]
return {
'title': 'EvAI Data Capsules',
'data': data,
'columns': columns,
'actions': actions,
'initial_sort': initial_sort,
'table_id': 'eveai_data_capsules_table',
'form_action': url_for('interaction_bp.handle_data_capsule_selection'),
'description': 'View all EvAI Data Capsules',
'table_height': 800
}