feat: show DAG status and job events in Activity panel

Connects dag_updated, dag_validated, and job lifecycle signals
from SiloEventListener to the Database Activity dock widget.

- dag.updated: inserts DAG sync status (node/edge count)
- dag.validated: inserts pass/fail badge with failed count
- job.created: inserts queued job entry
- job.completed: refreshes the full activity list
- job.failed: inserts error entry

Live entries are inserted at the top of the activity list,
styled in Catppuccin Blue, capped at 50 entries.

Closes kindred/create#219
This commit is contained in:
Zoe Forbes
2026-02-14 15:28:40 -06:00
parent 3d38e4b4c3
commit dc64a66f0f

View File

@@ -2732,6 +2732,11 @@ class SiloAuthDockWidget:
self._event_listener.revision_created.connect(self._on_remote_revision)
self._event_listener.connection_status.connect(self._on_sse_status)
self._event_listener.server_mode_changed.connect(self._on_server_mode)
self._event_listener.dag_updated.connect(self._on_dag_updated)
self._event_listener.dag_validated.connect(self._on_dag_validated)
self._event_listener.job_created.connect(self._on_job_created)
self._event_listener.job_completed.connect(self._on_job_completed)
self._event_listener.job_failed.connect(self._on_job_failed)
self._event_listener.start()
else:
if self._event_listener is not None and self._event_listener.isRunning():
@@ -2811,6 +2816,70 @@ class SiloAuthDockWidget:
)
self._refresh_activity_panel()
def _on_dag_updated(self, part_number, node_count, edge_count):
FreeCAD.Console.PrintMessage(
f"Silo: DAG updated for {part_number}"
f" ({node_count} nodes, {edge_count} edges)\n"
)
self._add_activity_entry(
f"\u25b6 {part_number} \u2013 DAG synced"
f" ({node_count} nodes, {edge_count} edges)",
part_number,
)
def _on_dag_validated(self, part_number, valid, failed_count):
if valid:
status = "\u2713 PASS"
FreeCAD.Console.PrintMessage(f"Silo: Validation passed for {part_number}\n")
else:
status = f"\u2717 FAIL ({failed_count} failed)"
FreeCAD.Console.PrintWarning(
f"Silo: Validation failed for {part_number}"
f" ({failed_count} features failed)\n"
)
self._add_activity_entry(f"{status} \u2013 {part_number}", part_number)
def _on_job_created(self, job_id, definition_name, part_number):
FreeCAD.Console.PrintMessage(
f"Silo: Job {definition_name} created for {part_number}\n"
)
self._add_activity_entry(
f"\u23f3 {part_number} \u2013 {definition_name} queued",
part_number,
)
def _on_job_completed(self, job_id):
FreeCAD.Console.PrintMessage(f"Silo: Job {job_id} completed\n")
self._refresh_activity_panel()
def _on_job_failed(self, job_id, error):
FreeCAD.Console.PrintError(f"Silo: Job {job_id} failed: {error}\n")
self._add_activity_entry(f"\u2717 Job {job_id[:8]} failed: {error}", None)
def _add_activity_entry(self, text, part_number):
"""Insert a live event entry at the top of the Activity panel."""
from PySide import QtCore, QtGui, QtWidgets
mw = FreeCADGui.getMainWindow()
if mw is None:
return
panel = mw.findChild(QtWidgets.QDockWidget, "SiloDatabaseActivity")
if panel is None:
return
activity_list = panel.findChild(QtWidgets.QListWidget)
if activity_list is None:
return
item = QtWidgets.QListWidgetItem(text)
if part_number:
item.setData(QtCore.Qt.UserRole, part_number)
item.setForeground(QtGui.QColor("#89b4fa"))
activity_list.insertItem(0, item)
# Cap the list at 50 entries
while activity_list.count() > 50:
activity_list.takeItem(activity_list.count() - 1)
def _refresh_activity_panel(self):
"""Refresh the Database Activity panel if it exists."""
from PySide import QtCore, QtGui, QtWidgets