mirror of
https://github.com/dromara/hertzbeat.git
synced 2026-09-17 09:40:58 +00:00
[fix] keep monitor selection across pages in monitor list (#4170)
Co-authored-by: aias00 <liuhongyu@apache.org>
This commit is contained in:
@@ -140,19 +140,6 @@
|
||||
</app-toolbar>
|
||||
|
||||
<div class="monitor-card-list">
|
||||
<div class="monitor-list-header" *ngIf="monitors?.length">
|
||||
<div class="monitor-header-actions">
|
||||
<label nz-checkbox [(ngModel)]="checkedAll" (ngModelChange)="onAllChecked($event)"></label>
|
||||
<nz-pagination
|
||||
[(nzPageIndex)]="pageIndex"
|
||||
[nzPageSize]="pageSize"
|
||||
[nzTotal]="total"
|
||||
(nzPageIndexChange)="onPageIndexChange($event)"
|
||||
nzSimple
|
||||
></nz-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nz-spin [nzSpinning]="tableLoading">
|
||||
<div class="monitor-card-list-content">
|
||||
<div
|
||||
@@ -293,6 +280,30 @@
|
||||
</div>
|
||||
</div>
|
||||
</nz-spin>
|
||||
|
||||
<div class="monitor-list-footer" *ngIf="monitors?.length">
|
||||
<div class="monitor-footer-actions">
|
||||
<ng-container *ngIf="checkedMonitorIds.size > 0">
|
||||
<label nz-checkbox [ngModel]="checkedAll" (ngModelChange)="onAllChecked($event)">
|
||||
{{ 'monitor.select-current-page' | i18n }}
|
||||
</label>
|
||||
<span class="monitor-selected-count">{{ 'monitor.selected-count' | i18n : { count: checkedMonitorIds.size } }}</span>
|
||||
<button nz-button nzType="link" nzSize="small" (click)="clearSelection()">
|
||||
{{ 'monitor.clear-selection' | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<nz-pagination
|
||||
[(nzPageIndex)]="pageIndex"
|
||||
[nzPageSize]="pageSize"
|
||||
[nzTotal]="total"
|
||||
[nzShowTotal]="rangeTemplate"
|
||||
nzShowSizeChanger
|
||||
[nzPageSizeOptions]="pageSizeOptions"
|
||||
(nzPageIndexChange)="onPageIndexChange($event)"
|
||||
(nzPageSizeChange)="onPageSizeChange($event)"
|
||||
></nz-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }} </ng-template>
|
||||
|
||||
@@ -86,19 +86,27 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.monitor-list-header {
|
||||
.monitor-selected-count {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.monitor-list-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
padding: 8px 0;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.monitor-header-actions {
|
||||
.monitor-footer-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
// Align the select-all checkbox with the per-row checkboxes, which sit at the card's 12px padding.
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.monitor-card-list-content {
|
||||
|
||||
@@ -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<number>();
|
||||
this.tableLoading = true;
|
||||
this.loadMonitorTable();
|
||||
@@ -134,7 +135,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
|
||||
message => {
|
||||
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 +181,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 +205,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 +304,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 +450,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 +512,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 +539,28 @@ 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Clear the whole cross-page selection in one click, so users aren't forced to page back to deselect (#4164).
|
||||
clearSelection() {
|
||||
this.checkedMonitorIds.clear();
|
||||
}
|
||||
|
||||
onItemChecked(monitorId: number, checked: boolean) {
|
||||
@@ -566,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() {
|
||||
|
||||
@@ -863,6 +863,9 @@
|
||||
"monitor.edit.success": "Update Monitor Success",
|
||||
"monitor.enable": "Enable",
|
||||
"monitor.export": "Export Selected",
|
||||
"monitor.selected-count": "{{count}} selected",
|
||||
"monitor.clear-selection": "Clear",
|
||||
"monitor.select-current-page": "Select this page",
|
||||
"monitor.export-all": "Export All",
|
||||
"monitor.export.switch-type": "Please select the export file format",
|
||||
"monitor.export.use-type": "Export selected monitors in {{type}} format",
|
||||
|
||||
@@ -822,6 +822,9 @@
|
||||
"monitor.edit.success": "モニターの更新に成功しました",
|
||||
"monitor.enable": "モニターを再開",
|
||||
"monitor.export": "モニターをエクスポート",
|
||||
"monitor.selected-count": "{{count}} 件選択中",
|
||||
"monitor.clear-selection": "クリア",
|
||||
"monitor.select-current-page": "現在のページを全選択",
|
||||
"monitor.export.switch-type": "エクスポートファイル形式を選択してください!",
|
||||
"monitor.export.use-type": "{{type}}ファイル形式でモニターをエクスポート",
|
||||
"monitor.grafana.enabled.label": "Grafanaを有効化",
|
||||
|
||||
@@ -634,6 +634,9 @@
|
||||
"monitor.edit.success": "Monitor modificado com sucesso",
|
||||
"monitor.enable": "Retomar monitoramento",
|
||||
"monitor.export": "Exportar monitor",
|
||||
"monitor.selected-count": "{{count}} selecionado(s)",
|
||||
"monitor.clear-selection": "Limpar",
|
||||
"monitor.select-current-page": "Selecionar esta página",
|
||||
"monitor.export.switch-type": "Selecione o formato do arquivo de exportação!",
|
||||
"monitor.export.use-type": "Exportar monitor no formato {{type}}",
|
||||
"monitor.grafana.enabled.label": "Habilitar Grafana",
|
||||
|
||||
@@ -866,6 +866,9 @@
|
||||
"monitor.edit.success": "修改监控成功",
|
||||
"monitor.enable": "恢复监控",
|
||||
"monitor.export": "导出所选",
|
||||
"monitor.selected-count": "已选 {{count}} 项",
|
||||
"monitor.clear-selection": "清空",
|
||||
"monitor.select-current-page": "全选当前页",
|
||||
"monitor.export-all": "导出全部",
|
||||
"monitor.export.switch-type": "请选择导出文件格式!",
|
||||
"monitor.export.use-type": "以 {{type}} 文件格式导出所选监控",
|
||||
|
||||
@@ -826,6 +826,9 @@
|
||||
"monitor.edit.success": "修改監控成功",
|
||||
"monitor.enable": "恢復監控",
|
||||
"monitor.export": "匯出監控",
|
||||
"monitor.selected-count": "已選 {{count}} 項",
|
||||
"monitor.clear-selection": "清空",
|
||||
"monitor.select-current-page": "全選當前頁",
|
||||
"monitor.export.switch-type": "請選擇匯出文件格式!",
|
||||
"monitor.export.use-type": "以 {{type}} 檔案格式匯出監控",
|
||||
"monitor.grafana.enabled.label": "啓用Grafana監控",
|
||||
|
||||
Reference in New Issue
Block a user