Add Report Issue button to tool details panel

- Client: add submit_issue() method for POST /tools/{owner}/{name}/issues
- New IssueDialog with type (bug/compatibility/security), severity, title,
  and description fields with character count and validation
- Report Issue button in rating bar beside Rate Tool, visible for registry
  tools only. Submits via background SubmitIssueWorker thread.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
rob
2026-01-30 03:31:27 -04:00
co-authored by Claude Opus 4.5
parent a486bb6d45
commit 23631ff4e7
3 changed files with 248 additions and 0 deletions
+69
View File
@@ -316,6 +316,38 @@ class DeleteReviewWorker(QThread):
self.error.emit(str(e))
class SubmitIssueWorker(QThread):
"""Background worker to submit an issue."""
finished = Signal(str)
error = Signal(str)
def __init__(self, owner: str, name: str, issue_type: str,
severity: str, title: str, description: str):
super().__init__()
self.owner = owner
self.name = name
self.issue_type = issue_type
self.severity = severity
self.title = title
self.description = description
def run(self):
from ...registry_client import RegistryClient, RegistryError
try:
config = load_config()
client = RegistryClient()
client.token = config.registry.token
client.submit_issue(
self.owner, self.name, self.issue_type,
self.severity, self.title, self.description
)
self.finished.emit("Issue reported successfully")
except RegistryError as e:
self.error.emit(e.message)
except Exception as e:
self.error.emit(str(e))
class ToolsPage(QWidget):
"""Main tools management page."""
@@ -330,6 +362,7 @@ class ToolsPage(QWidget):
self._rating_cache: Dict[str, Dict] = {} # tool_name -> {rating, my_review}
self._rating_worker = None
self._review_worker = None
self._issue_worker = None
self._my_slug: Optional[str] = None # Cached current user slug
self._my_slug_fetched = False
self._setup_ui()
@@ -413,6 +446,11 @@ class ToolsPage(QWidget):
self.btn_rate.setToolTip("Local tools can't be rated")
rating_bar_layout.addWidget(self.btn_rate)
self.btn_report_issue = QPushButton("Report Issue")
self.btn_report_issue.setObjectName("secondary")
self.btn_report_issue.clicked.connect(self._report_issue)
rating_bar_layout.addWidget(self.btn_report_issue)
self.rating_bar.setVisible(False)
info_layout.addWidget(self.rating_bar)
@@ -1130,6 +1168,37 @@ class ToolsPage(QWidget):
"""Handle review action error."""
self.main_window.show_status(f"Review error: {error}")
def _report_issue(self):
"""Open the issue report dialog for the selected tool."""
if not self._current_tool:
return
tool_name = self._get_qualified_name() or self._current_tool.name
registry_info = get_tool_registry_info(tool_name, self._my_slug)
if not registry_info:
return
owner, name = registry_info
from ..dialogs.issue_dialog import IssueDialog
dialog = IssueDialog(self, owner, name)
if not dialog.exec():
return
data = dialog.get_issue_data()
self._issue_worker = SubmitIssueWorker(
owner, name, data["issue_type"], data["severity"],
data["title"], data["description"]
)
self._issue_worker.finished.connect(
lambda msg: self.main_window.show_status(msg)
)
self._issue_worker.error.connect(
lambda err: self.main_window.show_status(f"Issue report failed: {err}")
)
self._issue_worker.start()
def _sync_tool_status(self):
"""Sync the moderation status of the selected tool from the registry."""
if not self._current_tool: