fix(ui): Monitoring Overview now reads like the wireframe, and the rail stops overlapping
Two problems, both only visible at the window size this machine actually opens
(1024×571 on a 1280×672 work area):
* The rail drew the "GẦN ĐÂY" heading on top of the last nav row. nav and the
bottom group have fixed heights, so a short window put the entire squeeze on
RECENTS; once that hit zero the layout had nowhere left to give. The
destinations and RECENTS now scroll together inside their own area, while
the bottom group, Settings and the account row stay pinned.
* Overview did not look like the drawing. Fixed, in the order the page draws
them: sections are quiet caps headings with flat content instead of six
bordered boxes; the four resource metrics sit ACROSS one row rather than
stacked four deep; and "Hoạt động gần đây" moved from second place to the
bottom beside the audit log, so the reading order is cost → machine →
permissions → prices → what happened. At 1280×760 the page now reaches the
price table on first screen; before it showed one and a half sections.
Two deliberate differences from the drawing, both because matching it would
remove information: the wireframe shows four KPI tiles where the app has five
real metrics plus the budget entry card, and it writes resources as one text
line where the app keeps the CPU/RAM gauges.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+37
-17
@@ -417,6 +417,7 @@ class MonitoringTab(QWidget):
|
||||
|
||||
# ---- Token Usage & Cost --------------------------------------------
|
||||
self.ov_usage_group = QGroupBox()
|
||||
self.ov_usage_group.setObjectName("monSection")
|
||||
usage_lay = QGridLayout(self.ov_usage_group)
|
||||
usage_lay.setSpacing(8)
|
||||
self.ov_usage_total = StatCard()
|
||||
@@ -447,41 +448,54 @@ class MonitoringTab(QWidget):
|
||||
|
||||
# ---- Recent Activity ----------------------------------------------
|
||||
self.ov_activity_group = QGroupBox()
|
||||
self.ov_activity_group.setObjectName("monSection")
|
||||
act_lay = QVBoxLayout(self.ov_activity_group)
|
||||
self.ov_activity_lbl = QLabel()
|
||||
self.ov_activity_lbl.setWordWrap(True)
|
||||
self.ov_activity_lbl.setTextFormat(Qt.RichText)
|
||||
act_lay.addWidget(self.ov_activity_lbl)
|
||||
left.addWidget(self.ov_activity_group)
|
||||
# added near the bottom, beside the audit log — see below
|
||||
|
||||
# ---- Resource Usage -------------------------------------------------
|
||||
self.ov_resource_group = QGroupBox()
|
||||
res_lay = QVBoxLayout(self.ov_resource_group)
|
||||
self.ov_resource_group.setObjectName("monSection")
|
||||
res_lay = QHBoxLayout(self.ov_resource_group)
|
||||
res_lay.setSpacing(18)
|
||||
|
||||
def _bar_row():
|
||||
row = QHBoxLayout()
|
||||
lbl = QLabel(); lbl.setFixedWidth(70)
|
||||
bar = QProgressBar(); bar.setFixedHeight(8); bar.setTextVisible(False)
|
||||
val = QLabel(); val.setFixedWidth(90); val.setAlignment(Qt.AlignRight)
|
||||
row.addWidget(lbl); row.addWidget(bar, 1); row.addWidget(val)
|
||||
res_lay.addLayout(row)
|
||||
# One metric as a compact column: name, value, and the gauge under
|
||||
# them. The bars stay — the wireframe writes this section as a
|
||||
# single line, and dropping them would lose the at-a-glance load.
|
||||
cell = QVBoxLayout()
|
||||
cell.setSpacing(2)
|
||||
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
|
||||
|
||||
def _text_row():
|
||||
cell = QVBoxLayout()
|
||||
cell.setSpacing(2)
|
||||
row = QHBoxLayout()
|
||||
lbl = QLabel(); val = QLabel(); val.setAlignment(Qt.AlignRight)
|
||||
row.addWidget(lbl); row.addStretch(1); row.addWidget(val)
|
||||
res_lay.addLayout(row)
|
||||
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_mem_lbl, self.ov_mem_bar, self.ov_mem_val = _bar_row()
|
||||
self.ov_disk_lbl, self.ov_disk_val = _text_row()
|
||||
self.ov_network_lbl, self.ov_network_val = _text_row()
|
||||
res_lay.addStretch(1)
|
||||
|
||||
# ---- Model pricing (beside the CPU/resource group) ------------------
|
||||
self.ov_pricing_group = QGroupBox()
|
||||
self.ov_pricing_group.setObjectName("monSection")
|
||||
pg = QVBoxLayout(self.ov_pricing_group)
|
||||
phdr = QHBoxLayout()
|
||||
self.ov_pricing_ccy_lbl = QLabel(); self.ov_pricing_ccy_lbl.setObjectName("hint")
|
||||
@@ -524,6 +538,7 @@ class MonitoringTab(QWidget):
|
||||
|
||||
# ---- Sandbox Details --------------------------------------------
|
||||
self.ov_sandbox_details_group = QGroupBox()
|
||||
self.ov_sandbox_details_group.setObjectName("monSection")
|
||||
sbx_lay = QVBoxLayout(self.ov_sandbox_details_group)
|
||||
|
||||
def _kv():
|
||||
@@ -561,6 +576,7 @@ class MonitoringTab(QWidget):
|
||||
|
||||
# ---- Permissions -----------------------------------------------
|
||||
self.ov_permissions_group = QGroupBox()
|
||||
self.ov_permissions_group.setObjectName("monSection")
|
||||
perm_lay = QVBoxLayout(self.ov_permissions_group)
|
||||
|
||||
def _pkv():
|
||||
@@ -584,8 +600,12 @@ class MonitoringTab(QWidget):
|
||||
# ---- Model pricing — its own section, full width ------------------
|
||||
root.addWidget(self.ov_pricing_group)
|
||||
|
||||
# ---- What actually happened, last ---------------------------------
|
||||
root.addWidget(self.ov_activity_group)
|
||||
|
||||
# ---- Audit Log ----------------------------------------------------
|
||||
self.ov_audit_group = QGroupBox()
|
||||
self.ov_audit_group.setObjectName("monSection")
|
||||
audit_lay = QVBoxLayout(self.ov_audit_group)
|
||||
self.ov_audit_lbl = QLabel()
|
||||
self.ov_audit_lbl.setWordWrap(True)
|
||||
@@ -645,12 +665,12 @@ class MonitoringTab(QWidget):
|
||||
# A QGroupBox title treats "&" as a mnemonic marker, so "token & Chi
|
||||
# phí" rendered as "token _Chi phí". Double it to show a literal "&".
|
||||
self.ov_usage_group.setTitle(
|
||||
tr("monitoring.overview_usage_title").replace("&", "&&"))
|
||||
tr("monitoring.overview_usage_title").upper().replace("&", "&&"))
|
||||
self.ov_budget_card.apply_btn.setToolTip(tr("usage.budget_apply_tooltip"))
|
||||
self.ov_budget_card.budget_spin.setToolTip(tr("usage.budget_spin_tooltip"))
|
||||
|
||||
self.ov_activity_group.setTitle(tr("monitoring.overview_activity_title"))
|
||||
self.ov_resource_group.setTitle(tr("monitoring.overview_resource_title"))
|
||||
self.ov_activity_group.setTitle(tr("monitoring.overview_activity_title").upper())
|
||||
self.ov_resource_group.setTitle(tr("monitoring.overview_resource_title").upper())
|
||||
self.security_page.filter_edit.setPlaceholderText(tr("monitoring.filter_placeholder"))
|
||||
self.action_page.filter_edit.setPlaceholderText(tr("monitoring.filter_placeholder"))
|
||||
self.ov_cpu_lbl.setText(tr("monitoring.overview_res_cpu"))
|
||||
@@ -658,7 +678,7 @@ class MonitoringTab(QWidget):
|
||||
self.ov_disk_lbl.setText(tr("monitoring.overview_res_disk"))
|
||||
self.ov_network_lbl.setText(tr("monitoring.overview_res_network"))
|
||||
# model pricing panel
|
||||
self.ov_pricing_group.setTitle(tr("monitoring.pricing_title"))
|
||||
self.ov_pricing_group.setTitle(tr("monitoring.pricing_title").upper())
|
||||
self.ov_pricing_ccy_lbl.setText(tr("monitoring.pricing_currency"))
|
||||
self.ov_price_import_btn.setText(tr("monitoring.pricing_import"))
|
||||
self.ov_price_export_btn.setText(tr("monitoring.pricing_export"))
|
||||
@@ -670,7 +690,7 @@ class MonitoringTab(QWidget):
|
||||
tr("monitoring.pricing_col_maxout"), tr("monitoring.pricing_col_input"),
|
||||
tr("monitoring.pricing_col_output")])
|
||||
|
||||
self.ov_sandbox_details_group.setTitle(tr("monitoring.overview_sandbox_details_title"))
|
||||
self.ov_sandbox_details_group.setTitle(tr("monitoring.overview_sandbox_details_title").upper())
|
||||
self.ov_sbx_id_lbl.setText(tr("monitoring.overview_sandbox_id"))
|
||||
self.ov_sbx_status_lbl.setText(tr("monitoring.overview_status"))
|
||||
self.ov_sbx_created_lbl.setText(tr("monitoring.overview_created"))
|
||||
@@ -678,7 +698,7 @@ class MonitoringTab(QWidget):
|
||||
self.ov_sbx_edit_btn.setText(tr("monitoring.overview_edit"))
|
||||
self.ov_sbx_net_lbl.setText(tr("monitoring.overview_network_label"))
|
||||
|
||||
self.ov_permissions_group.setTitle(tr("monitoring.overview_permissions_title"))
|
||||
self.ov_permissions_group.setTitle(tr("monitoring.overview_permissions_title").upper())
|
||||
self.ov_perm_fs_lbl.setText(tr("monitoring.overview_perm_fs"))
|
||||
self.ov_perm_fs_val.setText(tr("monitoring.overview_perm_fs_value"))
|
||||
self.ov_perm_network_lbl.setText(tr("monitoring.overview_perm_network"))
|
||||
@@ -688,7 +708,7 @@ class MonitoringTab(QWidget):
|
||||
self.ov_perm_env_val.setText(tr("monitoring.overview_perm_env_value"))
|
||||
self.ov_perm_edit_btn.setText(tr("monitoring.overview_edit"))
|
||||
|
||||
self.ov_audit_group.setTitle(tr("monitoring.overview_audit_title"))
|
||||
self.ov_audit_group.setTitle(tr("monitoring.overview_audit_title").upper())
|
||||
self.ov_view_all_btn.setText(tr("monitoring.overview_view_all"))
|
||||
|
||||
self.refresh()
|
||||
|
||||
Reference in New Issue
Block a user