From 909fb4a8ffb7e9695105251fa285b22595b2000c Mon Sep 17 00:00:00 2001 From: Steph Herbers Date: Tue, 6 Jan 2026 16:12:30 -0500 Subject: [PATCH 01/15] add new template and highlight logic --- apps/evaluations/tables.py | 8 ++++++ apps/evaluations/views/dataset_views.py | 2 +- .../evaluations/dataset_messages_table.html | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 templates/evaluations/dataset_messages_table.html diff --git a/apps/evaluations/tables.py b/apps/evaluations/tables.py index bc3db2afb8..4ecb4d1979 100644 --- a/apps/evaluations/tables.py +++ b/apps/evaluations/tables.py @@ -339,6 +339,14 @@ class DatasetMessagesTable(tables.Table): ] ) + def get_row_attrs(self, record): + attrs = { + **settings.DJANGO_TABLES2_ROW_ATTRS, + "x-data": f'{{"get isSelected() {{ return selectedMessageRow === {record.id} }}}}', + ":class": "{ 'bg-sky-100/40 dark:bg-sky-950/40': isSelected }", + } + return attrs + class Meta: model = EvaluationMessage fields = ( diff --git a/apps/evaluations/views/dataset_views.py b/apps/evaluations/views/dataset_views.py index d0d4caf10c..08acff3440 100644 --- a/apps/evaluations/views/dataset_views.py +++ b/apps/evaluations/views/dataset_views.py @@ -281,7 +281,7 @@ class DatasetMessagesTableView(LoginAndTeamRequiredMixin, SingleTableView, Permi model = EvaluationMessage table_class = DatasetMessagesTable table_pagination = {"per_page": 10} - template_name = "table/single_table.html" + template_name = "evaluations/dataset_messages_table.html" permission_required = "evaluations.view_evaluationdataset" def get_queryset(self): diff --git a/templates/evaluations/dataset_messages_table.html b/templates/evaluations/dataset_messages_table.html new file mode 100644 index 0000000000..eae51df3a3 --- /dev/null +++ b/templates/evaluations/dataset_messages_table.html @@ -0,0 +1,25 @@ +{% load static %} +{% load render_table from django_tables2 %} + +
+ {% render_table table "table/tailwind_js_pagination.html" %} +
+ + + +{% block modal %} +{% endblock modal %} From 2c4260f1e418de7a8e9042873d6e06833501ed92 Mon Sep 17 00:00:00 2001 From: Steph Herbers Date: Thu, 8 Jan 2026 11:33:24 -0500 Subject: [PATCH 02/15] rearrage row order and add message link --- apps/evaluations/models.py | 38 ++++++++++--------- .../views/evaluation_config_views.py | 21 ++++++++++ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/apps/evaluations/models.py b/apps/evaluations/models.py index d84dac6e8b..fc28aad92a 100644 --- a/apps/evaluations/models.py +++ b/apps/evaluations/models.py @@ -1,7 +1,7 @@ from __future__ import annotations import importlib -from collections import defaultdict +from collections import OrderedDict, defaultdict from functools import cached_property from typing import TYPE_CHECKING, Literal @@ -350,24 +350,28 @@ def get_table_data(self, include_ids: bool = False): for key, value in result.message_context.items() if key != "current_datetime" } - if include_ids is True: - table_by_message[result.message.id].update({"id": result.message.id}) - - table_by_message[result.message.id].update( - { - "Dataset Input": result.input_message, - "Dataset Output": result.output_message, - "Generated Response": result.output.get("generated_response", ""), - **{ - f"{key} ({result.evaluator.name})": value - for key, value in result.output.get("result", {}).items() - }, - **context_columns, - "session": result.session.external_id if result.session_id else "", - } + # Build row data in order + row_data = OrderedDict() + row_data["session"] = result.session.external_id if result.session_id else "" + row_data["message_id"] = result.message.id + row_data["Dataset Input"] = result.input_message + row_data["Dataset Output"] = result.output_message + row_data["Generated Response"] = result.output.get("generated_response", "") + + row_data.update( + {f"{key} ({result.evaluator.name})": value for key, value in result.output.get("result", {}).items()} ) + + row_data.update(context_columns) + if result.output.get("error"): - table_by_message[result.message.id]["error"] = result.output.get("error") + row_data["error"] = result.output.get("error") + + if include_ids is True: + row_data["id"] = result.message.id + + table_by_message[result.message.id] = row_data + return [{"#": index, **row} for index, row in enumerate(table_by_message.values())] diff --git a/apps/evaluations/views/evaluation_config_views.py b/apps/evaluations/views/evaluation_config_views.py index 5420eb436f..40059e8eda 100644 --- a/apps/evaluations/views/evaluation_config_views.py +++ b/apps/evaluations/views/evaluation_config_views.py @@ -271,6 +271,18 @@ def session_enabled_condition(_, record): # Check if session value exists (not empty string) return bool(record.get("session")) + def dataset_url_factory(_, __, record, value): + if not value: + return "#" + dataset_id = self.evaluation_run.config.dataset_id + message_id = record.get("message_id") + + url = reverse("evaluations:dataset_edit", args=[self.kwargs["team_slug"], dataset_id]) + return f"{url}?message_id={message_id}" + + def dataset_enabled_condition(_, record): + return bool(record.get("message_id")) + header = key.replace("_", " ").title() match key: case "session": @@ -282,9 +294,18 @@ def session_enabled_condition(_, record): url_factory=session_url_factory, enabled_condition=session_enabled_condition, ), + actions.chip_action( + label='', + url_factory=dataset_url_factory, + enabled_condition=dataset_enabled_condition, + open_url_in_new_tab=True, + ), ], align="right", ) + case "message_id": + # Skip rendering message_id as a separate column since it's now in session column + return None return columns.Column(verbose_name=header) From 0ec3d7e28f43064ee32f08d0d32147fa5ba77824 Mon Sep 17 00:00:00 2001 From: Steph Herbers Date: Thu, 8 Jan 2026 14:43:26 -0500 Subject: [PATCH 03/15] add mark_safe so icon is shown rather than string --- apps/evaluations/views/evaluation_config_views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/evaluations/views/evaluation_config_views.py b/apps/evaluations/views/evaluation_config_views.py index 40059e8eda..b58bad0700 100644 --- a/apps/evaluations/views/evaluation_config_views.py +++ b/apps/evaluations/views/evaluation_config_views.py @@ -11,6 +11,7 @@ from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.utils import timezone +from django.utils.safestring import mark_safe from django.views.decorators.http import require_http_methods, require_POST from django.views.generic import CreateView, TemplateView, UpdateView from django_tables2 import SingleTableView, columns, tables @@ -295,7 +296,7 @@ def dataset_enabled_condition(_, record): enabled_condition=session_enabled_condition, ), actions.chip_action( - label='', + label=mark_safe(''), url_factory=dataset_url_factory, enabled_condition=dataset_enabled_condition, open_url_in_new_tab=True, From ac63ac2b88eab796d184f3a81aed91a5f67a7200 Mon Sep 17 00:00:00 2001 From: Steph Herbers Date: Thu, 8 Jan 2026 16:26:41 -0500 Subject: [PATCH 04/15] add to hx-get request --- templates/evaluations/dataset_edit.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/evaluations/dataset_edit.html b/templates/evaluations/dataset_edit.html index 86e49872d7..1391b28710 100644 --- a/templates/evaluations/dataset_edit.html +++ b/templates/evaluations/dataset_edit.html @@ -56,7 +56,7 @@

{% translate "Dataset Creation Failed" %}

{% endif %}

{% translate "Dataset Messages" %}

From 78440a349f0922271205f0d429fa51a10b61be27 Mon Sep 17 00:00:00 2001 From: Steph Herbers Date: Thu, 8 Jan 2026 16:27:52 -0500 Subject: [PATCH 05/15] use different approach with get_table_kwargs --- apps/evaluations/tables.py | 11 +++-------- apps/evaluations/views/dataset_views.py | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/apps/evaluations/tables.py b/apps/evaluations/tables.py index 4ecb4d1979..14ab6bd7cf 100644 --- a/apps/evaluations/tables.py +++ b/apps/evaluations/tables.py @@ -339,13 +339,9 @@ class DatasetMessagesTable(tables.Table): ] ) - def get_row_attrs(self, record): - attrs = { - **settings.DJANGO_TABLES2_ROW_ATTRS, - "x-data": f'{{"get isSelected() {{ return selectedMessageRow === {record.id} }}}}', - ":class": "{ 'bg-sky-100/40 dark:bg-sky-950/40': isSelected }", - } - return attrs + def __init__(self, *args, highlight_message_id=None, **kwargs): + super().__init__(*args, **kwargs) + self.highlight_message_id = highlight_message_id class Meta: model = EvaluationMessage @@ -359,6 +355,5 @@ class Meta: "session_state", "actions", ) - row_attrs = settings.DJANGO_TABLES2_ROW_ATTRS orderable = False empty_text = "No messages in this dataset yet." diff --git a/apps/evaluations/views/dataset_views.py b/apps/evaluations/views/dataset_views.py index 08acff3440..ca2545e641 100644 --- a/apps/evaluations/views/dataset_views.py +++ b/apps/evaluations/views/dataset_views.py @@ -293,6 +293,23 @@ def get_queryset(self): evaluationdataset__id=dataset_id, evaluationdataset__team=self.request.team ).order_by("id") + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + try: + context["highlight_message_id"] = int(self.request.GET.get("message_id")) + except (ValueError, TypeError): + context["highlight_message_id"] = None + return context + + def get_table_kwargs(self): + kwargs = super().get_table_kwargs() + try: + highlight_id = int(self.request.GET.get("message_id")) + kwargs["highlight_message_id"] = highlight_id + except (ValueError, TypeError): + kwargs["highlight_message_id"] = None + return kwargs + @login_and_team_required @require_POST From f5422102e65ebf766b318b316b5b89125e836a5e Mon Sep 17 00:00:00 2001 From: Steph Herbers Date: Thu, 8 Jan 2026 16:28:20 -0500 Subject: [PATCH 06/15] update templates --- .../evaluations/dataset_messages_table.html | 32 ++++++++++--------- .../dataset_messages_table_render.html | 21 ++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 templates/evaluations/dataset_messages_table_render.html diff --git a/templates/evaluations/dataset_messages_table.html b/templates/evaluations/dataset_messages_table.html index eae51df3a3..051183fd16 100644 --- a/templates/evaluations/dataset_messages_table.html +++ b/templates/evaluations/dataset_messages_table.html @@ -1,25 +1,27 @@ {% load static %} {% load render_table from django_tables2 %} -
- {% render_table table "table/tailwind_js_pagination.html" %} -
+{% render_table table "evaluations/dataset_messages_table_render.html" %} +{% if highlight_message_id %} +{% endif %} {% block modal %} {% endblock modal %} diff --git a/templates/evaluations/dataset_messages_table_render.html b/templates/evaluations/dataset_messages_table_render.html new file mode 100644 index 0000000000..a2945cab5f --- /dev/null +++ b/templates/evaluations/dataset_messages_table_render.html @@ -0,0 +1,21 @@ +{% extends "table/tailwind_js_pagination.html" %} +{% load django_tables2 %} + +{% block table.tbody %} + + {% for record in table.page.object_list|default:table.data %} + + {% for column, cell in record.items %} + {% if column.visible %} + {{ cell }} + {% endif %} + {% endfor %} + + {% empty %} + {% if table.empty_text %} + {{ table.empty_text }} + {% endif %} + {% endfor %} + +{% endblock table.tbody %} From da9d6feff6363227cbb54483cb3539e2136804d0 Mon Sep 17 00:00:00 2001 From: Steph Herbers Date: Fri, 9 Jan 2026 14:03:10 -0500 Subject: [PATCH 07/15] code rabbit: Improve selector specificity to avoid false positive matches --- templates/evaluations/dataset_messages_table.html | 7 ++++--- templates/evaluations/dataset_messages_table_render.html | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/templates/evaluations/dataset_messages_table.html b/templates/evaluations/dataset_messages_table.html index 051183fd16..154ee6c80d 100644 --- a/templates/evaluations/dataset_messages_table.html +++ b/templates/evaluations/dataset_messages_table.html @@ -6,9 +6,10 @@ {% if highlight_message_id %}