fix(monitoring): Overview's middle sections are one line each, as drawn
The KPI row already matched the wireframe, but the two sections under it did
not, which is what still read as "unchanged":
* TÀI NGUYÊN was four stretched columns — on a 1900px screen each value sat
at the far right of its quarter, with a 700px progress bar drawn as a rule
between. It is now one line: CPU 0% · Bộ nhớ 141 MB · Disk I/O 1 MB/s ·
Mạng 1 KB/s, packed left. 130px → 57px. The bars are kept and still
updated, just not drawn.
* SANDBOX and QUYỀN were two four-row columns side by side. The wireframe
draws ONE section with one line, so they are merged: the summary line
carries file system · network · process · resource limits, and both the
sandbox rows (ID, created, uptime) and the permission rows sit behind a
"Chi tiết" fold. Nothing is dropped — 168px → 80px closed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2388,6 +2388,10 @@ STRINGS: Dict[str, Dict[str, str]] = {
|
|||||||
"monitoring.col_action": {"en": "Action", "ja": "アクション", "vi": "Hành động"},
|
"monitoring.col_action": {"en": "Action", "ja": "アクション", "vi": "Hành động"},
|
||||||
# The fourth KPI tile on Overview, as the wireframe labels it.
|
# The fourth KPI tile on Overview, as the wireframe labels it.
|
||||||
"monitoring.overview_calls": {"en": "Calls", "ja": "呼び出し", "vi": "Lượt gọi"},
|
"monitoring.overview_calls": {"en": "Calls", "ja": "呼び出し", "vi": "Lượt gọi"},
|
||||||
|
# The fold under the Sandbox summary line — the wireframe shows only the
|
||||||
|
# summary, so the ID / created / uptime / limits rows live behind this.
|
||||||
|
"monitoring.overview_sbx_detail": {
|
||||||
|
"en": "Details", "ja": "詳細", "vi": "Chi tiết"},
|
||||||
"monitoring.col_detail": {"en": "Detail", "ja": "詳細", "vi": "Chi tiết"},
|
"monitoring.col_detail": {"en": "Detail", "ja": "詳細", "vi": "Chi tiết"},
|
||||||
"monitoring.col_account": {"en": "Account", "ja": "アカウント", "vi": "Tài khoản"},
|
"monitoring.col_account": {"en": "Account", "ja": "アカウント", "vi": "Tài khoản"},
|
||||||
"monitoring.col_machine": {"en": "Machine", "ja": "マシン", "vi": "Máy"},
|
"monitoring.col_machine": {"en": "Machine", "ja": "マシン", "vi": "Máy"},
|
||||||
|
|||||||
+63
-28
@@ -497,39 +497,42 @@ class MonitoringTab(QWidget):
|
|||||||
# ---- Resource Usage -------------------------------------------------
|
# ---- Resource Usage -------------------------------------------------
|
||||||
self.ov_resource_group = QGroupBox()
|
self.ov_resource_group = QGroupBox()
|
||||||
self.ov_resource_group.setObjectName("monSection")
|
self.ov_resource_group.setObjectName("monSection")
|
||||||
|
# ONE compact line, as the wireframe writes it: name and value sit
|
||||||
|
# together and the pairs are separated by a middle dot, packed left —
|
||||||
|
# spread across the full width they read as four unrelated columns with
|
||||||
|
# the value stranded at the far edge of a 1900px screen.
|
||||||
res_lay = QHBoxLayout(self.ov_resource_group)
|
res_lay = QHBoxLayout(self.ov_resource_group)
|
||||||
res_lay.setSpacing(18)
|
res_lay.setSpacing(6)
|
||||||
|
self._res_first = True
|
||||||
|
|
||||||
|
def _pair():
|
||||||
|
if not self._res_first:
|
||||||
|
sep = QLabel("·")
|
||||||
|
sep.setObjectName("hint")
|
||||||
|
res_lay.addWidget(sep)
|
||||||
|
self._res_first = False
|
||||||
|
lbl = QLabel(); lbl.setObjectName("hint")
|
||||||
|
val = QLabel()
|
||||||
|
res_lay.addWidget(lbl)
|
||||||
|
res_lay.addWidget(val)
|
||||||
|
return lbl, val
|
||||||
|
|
||||||
def _bar_row():
|
def _bar_row():
|
||||||
# One metric as a compact column: name, value, and the gauge under
|
# The gauge is kept and updated, but off the line: at a glance the
|
||||||
# them. The bars stay — the wireframe writes this section as a
|
# number is what is read, and the bar was drawing a 700px rule.
|
||||||
# single line, and dropping them would lose the at-a-glance load.
|
lbl, val = _pair()
|
||||||
cell = QVBoxLayout()
|
bar = QProgressBar()
|
||||||
cell.setSpacing(2)
|
bar.setVisible(False)
|
||||||
top = QHBoxLayout()
|
|
||||||
lbl = QLabel()
|
|
||||||
val = QLabel(); val.setAlignment(Qt.AlignRight)
|
|
||||||
top.addWidget(lbl); top.addStretch(1); top.addWidget(val)
|
|
||||||
bar = QProgressBar(); bar.setFixedHeight(6); bar.setTextVisible(False)
|
|
||||||
cell.addLayout(top); cell.addWidget(bar)
|
|
||||||
res_lay.addLayout(cell, 1)
|
|
||||||
return lbl, bar, val
|
return lbl, bar, val
|
||||||
|
|
||||||
def _text_row():
|
def _text_row():
|
||||||
cell = QVBoxLayout()
|
return _pair()
|
||||||
cell.setSpacing(2)
|
|
||||||
row = QHBoxLayout()
|
|
||||||
lbl = QLabel(); val = QLabel(); val.setAlignment(Qt.AlignRight)
|
|
||||||
row.addWidget(lbl); row.addStretch(1); row.addWidget(val)
|
|
||||||
cell.addLayout(row)
|
|
||||||
cell.addSpacing(6)
|
|
||||||
res_lay.addLayout(cell, 1)
|
|
||||||
return lbl, val
|
|
||||||
|
|
||||||
self.ov_cpu_lbl, self.ov_cpu_bar, self.ov_cpu_val = _bar_row()
|
self.ov_cpu_lbl, self.ov_cpu_bar, self.ov_cpu_val = _bar_row()
|
||||||
self.ov_mem_lbl, self.ov_mem_bar, self.ov_mem_val = _bar_row()
|
self.ov_mem_lbl, self.ov_mem_bar, self.ov_mem_val = _bar_row()
|
||||||
self.ov_disk_lbl, self.ov_disk_val = _text_row()
|
self.ov_disk_lbl, self.ov_disk_val = _text_row()
|
||||||
self.ov_network_lbl, self.ov_network_val = _text_row()
|
self.ov_network_lbl, self.ov_network_val = _text_row()
|
||||||
|
res_lay.addStretch(1)
|
||||||
|
|
||||||
# ---- Model pricing (beside the CPU/resource group) ------------------
|
# ---- Model pricing (beside the CPU/resource group) ------------------
|
||||||
self.ov_pricing_group = QGroupBox()
|
self.ov_pricing_group = QGroupBox()
|
||||||
@@ -578,6 +581,22 @@ class MonitoringTab(QWidget):
|
|||||||
self.ov_sandbox_details_group = QGroupBox()
|
self.ov_sandbox_details_group = QGroupBox()
|
||||||
self.ov_sandbox_details_group.setObjectName("monSection")
|
self.ov_sandbox_details_group.setObjectName("monSection")
|
||||||
sbx_lay = QVBoxLayout(self.ov_sandbox_details_group)
|
sbx_lay = QVBoxLayout(self.ov_sandbox_details_group)
|
||||||
|
self.ov_sbx_summary = QLabel()
|
||||||
|
self.ov_sbx_summary.setWordWrap(True)
|
||||||
|
sbx_lay.addWidget(self.ov_sbx_summary)
|
||||||
|
self.ov_sbx_more_btn = QPushButton()
|
||||||
|
self.ov_sbx_more_btn.setObjectName("co4eSectionAction")
|
||||||
|
self.ov_sbx_more_btn.setFlat(True)
|
||||||
|
self.ov_sbx_more_btn.setCheckable(True)
|
||||||
|
self.ov_sbx_more_btn.setCursor(Qt.PointingHandCursor)
|
||||||
|
sbx_lay.addWidget(self.ov_sbx_more_btn, 0, Qt.AlignLeft)
|
||||||
|
self._sbx_detail = QWidget()
|
||||||
|
self._sbx_detail.setVisible(False)
|
||||||
|
self.ov_sbx_more_btn.toggled.connect(self._sbx_detail.setVisible)
|
||||||
|
self.ov_sbx_more_btn.toggled.connect(self._sync_sbx_more_label)
|
||||||
|
sbx_lay.addWidget(self._sbx_detail)
|
||||||
|
sbx_lay = QVBoxLayout(self._sbx_detail)
|
||||||
|
sbx_lay.setContentsMargins(0, 4, 0, 0)
|
||||||
|
|
||||||
def _kv():
|
def _kv():
|
||||||
row = QHBoxLayout()
|
row = QHBoxLayout()
|
||||||
@@ -607,10 +626,7 @@ class MonitoringTab(QWidget):
|
|||||||
self.ov_sbx_net_lbl, self.ov_sbx_net_val = _kv()
|
self.ov_sbx_net_lbl, self.ov_sbx_net_val = _kv()
|
||||||
# Sandbox and Permissions answer the same question ("what is the agent
|
# Sandbox and Permissions answer the same question ("what is the agent
|
||||||
# allowed to touch?"), so they share one full-width row.
|
# allowed to touch?"), so they share one full-width row.
|
||||||
self._sbx_perm_row = QHBoxLayout()
|
root.addWidget(self.ov_sandbox_details_group)
|
||||||
self._sbx_perm_row.setSpacing(12)
|
|
||||||
self._sbx_perm_row.addWidget(self.ov_sandbox_details_group, 1)
|
|
||||||
root.addLayout(self._sbx_perm_row)
|
|
||||||
|
|
||||||
# ---- Permissions -----------------------------------------------
|
# ---- Permissions -----------------------------------------------
|
||||||
self.ov_permissions_group = QGroupBox()
|
self.ov_permissions_group = QGroupBox()
|
||||||
@@ -632,8 +648,9 @@ class MonitoringTab(QWidget):
|
|||||||
self.ov_perm_edit_btn = QPushButton()
|
self.ov_perm_edit_btn = QPushButton()
|
||||||
self.ov_perm_edit_btn.setFlat(True)
|
self.ov_perm_edit_btn.setFlat(True)
|
||||||
self.ov_perm_edit_btn.clicked.connect(self._open_settings_and_refresh)
|
self.ov_perm_edit_btn.clicked.connect(self._open_settings_and_refresh)
|
||||||
perm_lay.addWidget(self.ov_perm_edit_btn, 0, Qt.AlignRight)
|
perm_lay.addWidget(self.ov_perm_edit_btn, 0, Qt.AlignLeft)
|
||||||
self._sbx_perm_row.addWidget(self.ov_permissions_group, 1)
|
# Inside the same fold as the sandbox rows — one section, one line.
|
||||||
|
self._sbx_detail.layout().addWidget(self.ov_permissions_group)
|
||||||
|
|
||||||
# ---- Model pricing — its own section, full width ------------------
|
# ---- Model pricing — its own section, full width ------------------
|
||||||
root.addWidget(self.ov_pricing_group)
|
root.addWidget(self.ov_pricing_group)
|
||||||
@@ -898,6 +915,12 @@ class MonitoringTab(QWidget):
|
|||||||
ut.format_cost(sum(costs.values()), pricing, digits=2))
|
ut.format_cost(sum(costs.values()), pricing, digits=2))
|
||||||
self._refresh_budget()
|
self._refresh_budget()
|
||||||
|
|
||||||
|
def _sync_sbx_more_label(self, *_a) -> None:
|
||||||
|
"""Label the fold with what it will do next."""
|
||||||
|
open_ = self.ov_sbx_more_btn.isChecked()
|
||||||
|
self.ov_sbx_more_btn.setText(
|
||||||
|
("▾ " if open_ else "▸ ") + tr("monitoring.overview_sbx_detail"))
|
||||||
|
|
||||||
def _apply_budget(self) -> None:
|
def _apply_budget(self) -> None:
|
||||||
"""Persist the spin box's value as the new budget — starts a fresh
|
"""Persist the spin box's value as the new budget — starts a fresh
|
||||||
remaining-balance window (spend before now is no longer counted)."""
|
remaining-balance window (spend before now is no longer counted)."""
|
||||||
@@ -959,6 +982,18 @@ class MonitoringTab(QWidget):
|
|||||||
tr("monitoring.overview_network_disabled") if net_blocked
|
tr("monitoring.overview_network_disabled") if net_blocked
|
||||||
else tr("monitoring.overview_network_enabled"))
|
else tr("monitoring.overview_network_enabled"))
|
||||||
self._set_badge(self.ov_sbx_net_val, "badgeWarn" if net_blocked else "badgeSuccess")
|
self._set_badge(self.ov_sbx_net_val, "badgeWarn" if net_blocked else "badgeSuccess")
|
||||||
|
# The one line the wireframe shows; the detail above stays a fold away.
|
||||||
|
self.ov_sbx_summary.setText(" · ".join([
|
||||||
|
f'{tr("monitoring.overview_perm_fs")}: '
|
||||||
|
f'{tr("monitoring.overview_perm_fs_value")}',
|
||||||
|
f'{tr("monitoring.overview_perm_network")}: '
|
||||||
|
f'{tr("monitoring.overview_network_disabled") if net_blocked else tr("monitoring.overview_network_enabled")}',
|
||||||
|
f'{tr("monitoring.overview_perm_process")}: '
|
||||||
|
f'{tr("monitoring.overview_perm_process_value")}',
|
||||||
|
f'{tr("monitoring.overview_resource_limits")}: '
|
||||||
|
f'{", ".join(limit_parts) if limit_parts else tr("monitoring.na")}',
|
||||||
|
]))
|
||||||
|
self._sync_sbx_more_label()
|
||||||
|
|
||||||
self.ov_perm_network_val.setText(
|
self.ov_perm_network_val.setText(
|
||||||
tr("monitoring.overview_perm_network_blocked") if net_blocked
|
tr("monitoring.overview_perm_network_blocked") if net_blocked
|
||||||
|
|||||||
Reference in New Issue
Block a user