Move rating display and Rate button to bottom of tool details panel
Instead of the Rate button sitting in the action bar with Create/Edit/Delete, the average rating, review count, and Rate/Edit Rating button now appear as a bar at the bottom of the tool detail section where they contextually belong. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
14b3f3d856
commit
b1c73aba3f
|
|
@ -363,6 +363,29 @@ class ToolsPage(QWidget):
|
||||||
self.info_text.setPlaceholderText("Select a tool to view details")
|
self.info_text.setPlaceholderText("Select a tool to view details")
|
||||||
info_layout.addWidget(self.info_text)
|
info_layout.addWidget(self.info_text)
|
||||||
|
|
||||||
|
# Rating bar at bottom of details panel
|
||||||
|
self.rating_bar = QWidget()
|
||||||
|
rating_bar_layout = QHBoxLayout(self.rating_bar)
|
||||||
|
rating_bar_layout.setContentsMargins(4, 4, 4, 4)
|
||||||
|
rating_bar_layout.setSpacing(12)
|
||||||
|
|
||||||
|
self.rating_label = QLabel("")
|
||||||
|
self.rating_label.setTextFormat(Qt.RichText)
|
||||||
|
self.rating_label.setStyleSheet("color: #4a5568; font-size: 12px;")
|
||||||
|
rating_bar_layout.addWidget(self.rating_label)
|
||||||
|
|
||||||
|
rating_bar_layout.addStretch()
|
||||||
|
|
||||||
|
self.btn_rate = QPushButton("Rate Tool")
|
||||||
|
self.btn_rate.setObjectName("secondary")
|
||||||
|
self.btn_rate.clicked.connect(self._rate_tool)
|
||||||
|
self.btn_rate.setEnabled(False)
|
||||||
|
self.btn_rate.setToolTip("Local tools can't be rated")
|
||||||
|
rating_bar_layout.addWidget(self.btn_rate)
|
||||||
|
|
||||||
|
self.rating_bar.setVisible(False)
|
||||||
|
info_layout.addWidget(self.rating_bar)
|
||||||
|
|
||||||
right_layout.addWidget(info_box, 1)
|
right_layout.addWidget(info_box, 1)
|
||||||
|
|
||||||
splitter.addWidget(right)
|
splitter.addWidget(right)
|
||||||
|
|
@ -401,13 +424,6 @@ class ToolsPage(QWidget):
|
||||||
self.btn_delete.setEnabled(False)
|
self.btn_delete.setEnabled(False)
|
||||||
btn_layout.addWidget(self.btn_delete)
|
btn_layout.addWidget(self.btn_delete)
|
||||||
|
|
||||||
self.btn_rate = QPushButton("Rate Tool")
|
|
||||||
self.btn_rate.setObjectName("secondary")
|
|
||||||
self.btn_rate.clicked.connect(self._rate_tool)
|
|
||||||
self.btn_rate.setEnabled(False)
|
|
||||||
self.btn_rate.setToolTip("Local tools can't be rated")
|
|
||||||
btn_layout.addWidget(self.btn_rate)
|
|
||||||
|
|
||||||
btn_layout.addStretch()
|
btn_layout.addStretch()
|
||||||
|
|
||||||
# Connect/Publish button
|
# Connect/Publish button
|
||||||
|
|
@ -442,6 +458,7 @@ class ToolsPage(QWidget):
|
||||||
self.tool_tree.clear()
|
self.tool_tree.clear()
|
||||||
self._current_tool = None
|
self._current_tool = None
|
||||||
self.info_text.clear()
|
self.info_text.clear()
|
||||||
|
self.rating_bar.setVisible(False)
|
||||||
self._has_pending_tools = False # Reset, will be set during tree building
|
self._has_pending_tools = False # Reset, will be set during tree building
|
||||||
|
|
||||||
tools = list_tools()
|
tools = list_tools()
|
||||||
|
|
@ -628,6 +645,7 @@ class ToolsPage(QWidget):
|
||||||
if not items:
|
if not items:
|
||||||
self._current_tool = None
|
self._current_tool = None
|
||||||
self.info_text.clear()
|
self.info_text.clear()
|
||||||
|
self.rating_bar.setVisible(False)
|
||||||
self._update_buttons()
|
self._update_buttons()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -636,6 +654,7 @@ class ToolsPage(QWidget):
|
||||||
if not tool_name:
|
if not tool_name:
|
||||||
self._current_tool = None
|
self._current_tool = None
|
||||||
self.info_text.clear()
|
self.info_text.clear()
|
||||||
|
self.rating_bar.setVisible(False)
|
||||||
self._update_buttons()
|
self._update_buttons()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -737,43 +756,6 @@ class ToolsPage(QWidget):
|
||||||
f"<strong>Reason:</strong><br>{feedback_escaped}</div>"
|
f"<strong>Reason:</strong><br>{feedback_escaped}</div>"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Rating section (for registry-sourced tools)
|
|
||||||
registry_info = get_tool_registry_info(qname)
|
|
||||||
if registry_info:
|
|
||||||
cached = self._rating_cache.get(qname)
|
|
||||||
if cached:
|
|
||||||
rating_data = cached.get("rating")
|
|
||||||
my_review = cached.get("my_review")
|
|
||||||
if rating_data:
|
|
||||||
avg = rating_data.get("average_rating", 0)
|
|
||||||
count = rating_data.get("rating_count", 0)
|
|
||||||
if count > 0:
|
|
||||||
filled = round(avg)
|
|
||||||
stars_html = "".join(
|
|
||||||
"★" if i < filled else "☆" for i in range(5)
|
|
||||||
)
|
|
||||||
lines.append(
|
|
||||||
f"<p style='color: #d69e2e; font-size: 14px; margin-bottom: 4px;'>"
|
|
||||||
f"{stars_html} <span style='color: #4a5568; font-size: 12px;'>"
|
|
||||||
f"{avg:.1f}/5 from {count} review{'s' if count != 1 else ''}</span></p>"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
lines.append(
|
|
||||||
"<p style='color: #718096; font-size: 12px; margin-bottom: 4px;'>"
|
|
||||||
"No ratings yet</p>"
|
|
||||||
)
|
|
||||||
if my_review:
|
|
||||||
my_stars = "★" * my_review["rating"] + "☆" * (5 - my_review["rating"])
|
|
||||||
lines.append(
|
|
||||||
f"<p style='color: #805ad5; font-size: 12px; margin-bottom: 8px;'>"
|
|
||||||
f"Your rating: {my_stars}</p>"
|
|
||||||
)
|
|
||||||
elif registry_info:
|
|
||||||
lines.append(
|
|
||||||
"<p style='color: #718096; font-size: 12px; margin-bottom: 4px;'>"
|
|
||||||
"Loading ratings...</p>"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Source info
|
# Source info
|
||||||
if tool.source:
|
if tool.source:
|
||||||
source_type = tool.source.type
|
source_type = tool.source.type
|
||||||
|
|
@ -817,6 +799,40 @@ class ToolsPage(QWidget):
|
||||||
|
|
||||||
self.info_text.setHtml("\n".join(lines))
|
self.info_text.setHtml("\n".join(lines))
|
||||||
|
|
||||||
|
# Update rating bar below the detail text
|
||||||
|
self._update_rating_bar(qname)
|
||||||
|
|
||||||
|
def _update_rating_bar(self, qname: str):
|
||||||
|
"""Update the rating bar widget at the bottom of the detail panel."""
|
||||||
|
registry_info = get_tool_registry_info(qname)
|
||||||
|
if not registry_info:
|
||||||
|
self.rating_bar.setVisible(False)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.rating_bar.setVisible(True)
|
||||||
|
cached = self._rating_cache.get(qname)
|
||||||
|
|
||||||
|
if cached:
|
||||||
|
rating_data = cached.get("rating")
|
||||||
|
my_review = cached.get("my_review")
|
||||||
|
parts = []
|
||||||
|
if rating_data:
|
||||||
|
avg = rating_data.get("average_rating", 0)
|
||||||
|
count = rating_data.get("rating_count", 0)
|
||||||
|
if count > 0:
|
||||||
|
filled = round(avg)
|
||||||
|
stars = "".join("★" if i < filled else "☆" for i in range(5))
|
||||||
|
parts.append(f"<span style='color: #d69e2e; font-size: 14px;'>{stars}</span>"
|
||||||
|
f" {avg:.1f}/5 from {count} review{'s' if count != 1 else ''}")
|
||||||
|
else:
|
||||||
|
parts.append("No ratings yet")
|
||||||
|
if my_review:
|
||||||
|
my_stars = "★" * my_review["rating"] + "☆" * (5 - my_review["rating"])
|
||||||
|
parts.append(f"<span style='color: #805ad5;'>Your rating: {my_stars}</span>")
|
||||||
|
self.rating_label.setText(" · ".join(parts) if parts else "")
|
||||||
|
else:
|
||||||
|
self.rating_label.setText("Loading ratings...")
|
||||||
|
|
||||||
def _has_settings(self, tool: Tool) -> bool:
|
def _has_settings(self, tool: Tool) -> bool:
|
||||||
"""Check if a tool has configurable settings."""
|
"""Check if a tool has configurable settings."""
|
||||||
if not tool or not tool.path:
|
if not tool or not tool.path:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue