Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions database_api/model_taskitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from database_api.planexe_db_singleton import db
from sqlalchemy_utils import UUIDType
from sqlalchemy import JSON
from sqlalchemy.orm import column_property

class TaskState(enum.Enum):
pending = 1
Expand Down Expand Up @@ -70,6 +71,11 @@ class TaskItem(db.Model):
# Artifact schema/version marker (legacy snapshots are NULL/1, split-storage snapshots are 2+).
run_artifact_layout_version = db.Column(db.Integer, nullable=True, default=None)

# Lightweight admin/UI helpers; avoids loading large payload columns just to render links.
has_generated_report_html = column_property(generated_report_html.isnot(None))
has_run_zip_snapshot = column_property(run_zip_snapshot.isnot(None))
has_run_track_activity_jsonl = column_property(run_track_activity_jsonl.isnot(None))

def __repr__(self):
return f"{self.id}: {self.timestamp_created}, {self.state}, {self.prompt!r}, parameters: {self.parameters!r}"

Expand Down
22 changes: 15 additions & 7 deletions frontend_multi_user/src/planexe_modelviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from markupsafe import Markup
from flask import url_for, abort, redirect, Response
from flask_login import current_user
from sqlalchemy.orm import defer

class AdminOnlyModelView(ModelView):
"""Restrict admin views to authenticated admin users only."""
Expand Down Expand Up @@ -135,23 +136,30 @@ class TaskItemView(AdminOnlyModelView):
'prompt': lambda v, c, m, p: m.prompt[:100] + '...' if m.prompt and len(m.prompt) > 100 else m.prompt,
'view_plan': lambda v, c, m, p: Markup(
f'<a href="/viewplan?run_id={m.id}" target="_blank">View</a>'
) if m.generated_report_html else '—',
) if m.has_generated_report_html else '—',
'generated_report_html': lambda v, c, m, p: Markup(
f'<a href="{url_for("download_task_report", task_id=str(m.id))}">Download ({len(m.generated_report_html.encode("utf-8")) / 1024:.1f} KB)</a>'
) if m.generated_report_html else '—',
f'<a href="{url_for("download_task_report", task_id=str(m.id))}">Download</a>'
) if m.has_generated_report_html else '—',
'run_zip_snapshot': lambda v, c, m, p: Markup(
f'<a href="{url_for("download_task_run_zip", task_id=str(m.id))}">Download ({len(m.run_zip_snapshot) / 1024:.1f} KB)</a>'
) if m.run_zip_snapshot else '—',
f'<a href="{url_for("download_task_run_zip", task_id=str(m.id))}">Download</a>'
) if m.has_run_zip_snapshot else '—',
'run_activity_overview_json': lambda v, c, m, p: (
json.dumps(m.run_activity_overview_json, ensure_ascii=False)[:120] + '...'
if m.run_activity_overview_json and len(json.dumps(m.run_activity_overview_json, ensure_ascii=False)) > 120
else (json.dumps(m.run_activity_overview_json, ensure_ascii=False) if m.run_activity_overview_json else '—')
),
'run_track_activity': lambda v, c, m, p: Markup(
f'<a href="{url_for("download_task_track_activity", task_id=str(m.id))}">Download ({((m.run_track_activity_bytes if m.run_track_activity_bytes is not None else len(m.run_track_activity_jsonl.encode("utf-8"))) / 1024):.1f} KB)</a>'
) if m.run_track_activity_jsonl else '—',
f'<a href="{url_for("download_task_track_activity", task_id=str(m.id))}">Download</a>'
) if m.has_run_track_activity_jsonl else '—',
}

def get_query(self):
return super().get_query().options(
defer(self.model.generated_report_html),
defer(self.model.run_zip_snapshot),
defer(self.model.run_track_activity_jsonl),
)

class NonceItemView(AdminOnlyModelView):
"""Custom ModelView for NonceItem"""
def __init__(self, model, *args, **kwargs):
Expand Down