From ee419c8502ca002bebcd2f913b1b436b534cf43b Mon Sep 17 00:00:00 2001 From: Duansg Date: Sat, 20 Jun 2026 08:49:32 -0700 Subject: [PATCH 1/6] [fix] keep monitor selection across pages in monitor list (#4164) The batch-select checkboxes lost their checked state when paging: every table reload (pagination, auto-refresh, post-CRUD) eagerly cleared checkedMonitorIds, so selections made on a previous page disappeared. Persist the selection Set across reloads and only reset it when the result set actually changes (filter/app/label switch). The header "select all" is now a getter computed over the current page, toggling only this page's selectable monitors, and batch ops deselect just the ids they acted on. --- .../monitor-list/monitor-list.component.html | 2 +- .../monitor-list/monitor-list.component.ts | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html index 38fa55f5489..19278df8dc5 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html @@ -142,7 +142,7 @@
- + { filter$.unsubscribe(); this.tableLoading = false; - this.checkedAll = false; + // Filtering changes the result set, so the previous selection no longer applies. this.checkedMonitorIds.clear(); if (message.code === 0) { let page = message.data; @@ -180,8 +180,7 @@ export class MonitorListComponent implements OnInit, OnDestroy { .subscribe( message => { this.tableLoading = false; - this.checkedAll = false; - this.checkedMonitorIds.clear(); + // Keep the selection across reloads (pagination, auto-refresh, post-CRUD) so multi-page checks persist (#4164). if (message.code === 0) { let page = message.data; this.monitors = reconcile ? this.reconcileMonitorStates(page.content) : this.resetMonitorStates(page.content); @@ -205,8 +204,7 @@ export class MonitorListComponent implements OnInit, OnDestroy { .subscribe( message => { this.tableLoading = false; - this.checkedAll = false; - this.checkedMonitorIds.clear(); + // Keep the selection across pagination so checks made on other pages persist (#4164). if (message.code === 0) { let page = message.data; // Pagination changes the result set, so reconcile here would flag the previous page as "disappeared" (#4156). @@ -305,6 +303,7 @@ export class MonitorListComponent implements OnInit, OnDestroy { deleteMonitors$.unsubscribe(); if (message.code === 0) { this.notifySvc.success(this.i18nSvc.fanyi('common.notify.delete-success'), ''); + monitors.forEach(id => this.checkedMonitorIds.delete(id)); this.updatePageIndex(monitors.size); this.loadMonitorTable(); } else { @@ -450,6 +449,7 @@ export class MonitorListComponent implements OnInit, OnDestroy { cancelManage$.unsubscribe(); if (message.code === 0) { this.notifySvc.success(this.i18nSvc.fanyi('common.notify.cancel-success'), ''); + monitors.forEach(id => this.checkedMonitorIds.delete(id)); this.loadMonitorTable(); } else { this.tableLoading = false; @@ -511,6 +511,7 @@ export class MonitorListComponent implements OnInit, OnDestroy { enableManage$.unsubscribe(); if (message.code === 0) { this.notifySvc.success(this.i18nSvc.fanyi('common.notify.enable-success'), ''); + monitors.forEach(id => this.checkedMonitorIds.delete(id)); this.loadMonitorTable(); } else { this.tableLoading = false; @@ -537,14 +538,23 @@ export class MonitorListComponent implements OnInit, OnDestroy { } // begin: List multiple choice paging - checkedAll: boolean = false; + // Reflects only the current page: checked when every selectable monitor on this page is selected. + get checkedAll(): boolean { + const selectable = this.monitors?.filter(monitor => !this.isMonitorDisabled(monitor)) ?? []; + return selectable.length > 0 && selectable.every(monitor => this.checkedMonitorIds.has(monitor.id)); + } onAllChecked(checked: boolean) { - if (checked) { - this.monitors.forEach(monitor => this.checkedMonitorIds.add(monitor.id)); - } else { - this.checkedMonitorIds.clear(); - } + // Only toggle the current page's selectable monitors, leaving selections on other pages untouched (#4164). + this.monitors + ?.filter(monitor => !this.isMonitorDisabled(monitor)) + .forEach(monitor => { + if (checked) { + this.checkedMonitorIds.add(monitor.id); + } else { + this.checkedMonitorIds.delete(monitor.id); + } + }); } onItemChecked(monitorId: number, checked: boolean) { From 1ee42da8ce8709620141077c8704f618ed010dbd Mon Sep 17 00:00:00 2001 From: Duansg Date: Sat, 20 Jun 2026 09:18:22 -0700 Subject: [PATCH 2/6] [improve] show selected count and one-click clear for monitor batch selection With selection now persisting across pages, users could not tell how many monitors were selected or deselect them without paging back. Show a live "N selected" count and a one-click clear in the list header (i18n in 5 locales) so the cross-page selection stays visible and easy to reset. --- .../routes/monitor/monitor-list/monitor-list.component.html | 6 ++++++ .../routes/monitor/monitor-list/monitor-list.component.less | 6 ++++++ .../routes/monitor/monitor-list/monitor-list.component.ts | 5 +++++ web-app/src/assets/i18n/en-US.json | 2 ++ web-app/src/assets/i18n/ja-JP.json | 2 ++ web-app/src/assets/i18n/pt-BR.json | 2 ++ web-app/src/assets/i18n/zh-CN.json | 2 ++ web-app/src/assets/i18n/zh-TW.json | 2 ++ 8 files changed, 27 insertions(+) diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html index 19278df8dc5..833d55876c5 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html @@ -143,6 +143,12 @@
+ + {{ 'monitor.selected-count' | i18n : { count: checkedMonitorIds.size } }} + + Date: Sat, 20 Jun 2026 09:19:27 -0700 Subject: [PATCH 3/6] [improve] move monitor list pagination to the bottom The pager sat above the card list, so after scrolling through a page the user had to scroll back up to load the next one. Move it below the list and show page numbers plus the total count, matching the usual list pagination placement. --- .../monitor-list/monitor-list.component.html | 17 ++++++++++------- .../monitor-list/monitor-list.component.less | 9 +++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html index 833d55876c5..31a16043c46 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html @@ -149,13 +149,6 @@ {{ 'monitor.clear-selection' | i18n }} -
@@ -299,6 +292,16 @@
+ +
{{ 'common.total' | i18n }} {{ total }} diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less index 4d595c5df58..3ffbfa19709 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less @@ -107,6 +107,15 @@ font-size: 12px; } +.monitor-list-footer { + display: flex; + justify-content: flex-end; + align-items: center; + margin-top: 16px; + padding: 8px 0; + flex-wrap: wrap; +} + .monitor-card-list-content { position: relative; display: flex; From e1114283a5fa04eec0df5be7fdb2d54a8988d69a Mon Sep 17 00:00:00 2001 From: Duansg Date: Sat, 20 Jun 2026 11:44:56 -0700 Subject: [PATCH 4/6] [improve] label the monitor select-all checkbox A bare checkbox sitting alone in the list header looked out of place when nothing was selected. Add a "Select this page" label (i18n in 5 locales) so it reads as a clear action. --- .../routes/monitor/monitor-list/monitor-list.component.html | 4 +++- web-app/src/assets/i18n/en-US.json | 1 + web-app/src/assets/i18n/ja-JP.json | 1 + web-app/src/assets/i18n/pt-BR.json | 1 + web-app/src/assets/i18n/zh-CN.json | 1 + web-app/src/assets/i18n/zh-TW.json | 1 + 6 files changed, 8 insertions(+), 1 deletion(-) diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html index 31a16043c46..13b693bf47e 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html @@ -142,7 +142,9 @@
- + {{ 'monitor.selected-count' | i18n : { count: checkedMonitorIds.size } }} - -
-
-
diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts index afd4d9ea490..2ab34431793 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts @@ -53,7 +53,8 @@ export class MonitorListComponent implements OnInit, OnDestroy { app!: string | undefined; labels!: string | undefined; pageIndex: number = 1; - pageSize: number = 8; + pageSize: number = 10; + pageSizeOptions: number[] = [10, 20, 50]; total: number = 0; monitors!: Monitor[]; tableLoading: boolean = true; @@ -98,7 +99,7 @@ export class MonitorListComponent implements OnInit, OnDestroy { this.app = undefined; } this.pageIndex = 1; - this.pageSize = 8; + this.pageSize = 10; this.checkedMonitorIds = new Set(); this.tableLoading = true; this.loadMonitorTable(); @@ -581,6 +582,12 @@ export class MonitorListComponent implements OnInit, OnDestroy { this.changeMonitorTable(this.currentSortField, this.currentSortOrder); } + onPageSizeChange(pageSize: number) { + this.pageSize = pageSize; + this.pageIndex = 1; + this.changeMonitorTable(this.currentSortField, this.currentSortOrder); + } + // begin: app type search filter onSearchAppClicked() {