This is an automated email from the ASF dual-hosted git repository.

gongchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/master by this push:
     new 4ae6ba9a3c feat: update add monitors pop selected menus modal (#3878)
4ae6ba9a3c is described below

commit 4ae6ba9a3cf10315d79594f7ab6a220f168e920f
Author: Tomsun28 <[email protected]>
AuthorDate: Thu Dec 4 23:55:10 2025 +0800

    feat: update add monitors pop selected menus modal (#3878)
    
    Signed-off-by: tomsun28 <[email protected]>
    Co-authored-by: aias00 <[email protected]>
---
 .../docs/help/{mcp_sse_server.md => mcp_server.md} |   2 +-
 .../help/{mcp_sse_server.md => mcp_server.md}      |   2 +-
 home/sidebars.json                                 |   2 +-
 .../monitor-list/monitor-list.component.html       |  10 +-
 .../monitor-list/monitor-list.component.less       |  17 ++-
 .../routes/setting/define/define.component.html    |   4 +-
 .../monitor-select-list.component.html}            |   0
 .../monitor-select-list.component.less}            |   0
 .../monitor-select-list.component.spec.ts          |  43 ++++++
 .../monitor-select-list.component.ts}              |   8 +-
 .../monitor-select-menu.component.html             |  45 +++---
 .../monitor-select-menu.component.less             | 157 ++++++++++++++++++---
 .../monitor-select-menu.component.ts               |  21 +++
 web-app/src/app/shared/shared.module.ts            |   2 +
 web-app/src/assets/app-data.json                   |   2 +-
 15 files changed, 263 insertions(+), 52 deletions(-)

diff --git a/home/docs/help/mcp_sse_server.md b/home/docs/help/mcp_server.md
similarity index 99%
rename from home/docs/help/mcp_sse_server.md
rename to home/docs/help/mcp_server.md
index 0b600e70a4..82ec71cefa 100644
--- a/home/docs/help/mcp_sse_server.md
+++ b/home/docs/help/mcp_server.md
@@ -1,5 +1,5 @@
 ---
-id: mcp_sse_server
+id: mcp_server
 title: MCP Server
 sidebar_label: MCP Server
 keywords: [MCP, SSE, streaming, server]
diff --git 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_sse_server.md 
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_server.md
similarity index 99%
rename from 
home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_sse_server.md
rename to 
home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_server.md
index 7e260a5e4d..0e04620e19 100644
--- 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_sse_server.md
+++ b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_server.md
@@ -1,5 +1,5 @@
 ---
-id: mcp_sse_server
+id: mcp_server
 title: MCP 服务器
 sidebar_label: MCP 服务器
 keywords: [MCP, SSE, 流式传输, 服务器]
diff --git a/home/sidebars.json b/home/sidebars.json
index 1ea4b10d6d..4c9a149072 100755
--- a/home/sidebars.json
+++ b/home/sidebars.json
@@ -67,7 +67,7 @@
         "help/guide",
         "help/security_model",
         "help/ai_agent",
-        "help/mcp_sse_server",
+        "help/mcp_server",
         {
           "type": "category",
           "label": "use-case",
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 0dbd76053d..b980116f17 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
@@ -370,16 +370,17 @@
 <nz-modal
   [(nzVisible)]="appSwitchModalVisible"
   (nzOnCancel)="onAppSwitchModalCancel()"
-  nzClosable="false"
-  nzWidth="30%"
+  nzClosable="true"
+  nzWidth="900px"
   nzWrapClassName="monitor-select-menu-modal"
+  [nzTitle]="appSwitchModalVisibleType === 1 ? ('monitor.search.app' | i18n) : 
('monitor.new-monitor' | i18n)"
   [nzFooter]="null"
   [nzOkLoading]="appSearchLoading"
+  nzCentered
 >
   <div *nzModalContent class="-inner-content">
     <app-monitor-select-menu
-      listStyle="border-right: 0px"
-      [searchPlaceholder]="(appSwitchModalVisibleType === 1 ? 
'monitor.search.app' : 'monitor.center.search.placeholder') | i18n"
+      [searchPlaceholder]="'monitor.center.search.placeholder' | i18n"
       [loading]="appSearchLoading"
       [data]="appSearchOrigin"
       (selectedChanged)="gotoMonitorAddDetail($event)"
@@ -387,7 +388,6 @@
       <ng-template let-app="item" #prefix>
         <i nz-icon [nzType]="getAppIconName(app.value)" nzTheme="outline"></i>
       </ng-template>
-      <ng-template #suffix>@if (appSwitchModalVisibleType !== 1) {<i nz-icon 
nzType="right"></i>}</ng-template>
     </app-monitor-select-menu>
   </div>
 </nz-modal>
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 7817988a06..9a288de84b 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
@@ -2,10 +2,25 @@
 
 ::ng-deep {
   .monitor-select-menu-modal {
+    .ant-modal-body {
+      padding: 0;
+      max-height: 70vh;
+      overflow: hidden;
+    }
+
+    .-inner-content {
+      height: 70vh;
+      max-height: 70vh;
+    }
+
     .ant-spin-container {
-      max-height: 80vh;
+      max-height: 70vh;
       overflow: hidden;
     }
+
+    app-monitor-select-menu {
+      height: 100%;
+    }
   }
 }
 
diff --git a/web-app/src/app/routes/setting/define/define.component.html 
b/web-app/src/app/routes/setting/define/define.component.html
index 8cf4cf1dff..cbf0cff988 100755
--- a/web-app/src/app/routes/setting/define/define.component.html
+++ b/web-app/src/app/routes/setting/define/define.component.html
@@ -28,7 +28,7 @@
 
 <nz-layout style="height: 100vh; overflow: hidden">
   <nz-sider [nzTheme]="theme == 'dark' ? 'dark' : 'light'" style="height: 
100%; overflow: hidden" [nzTrigger]="null">
-    <app-monitor-select-menu
+    <app-monitor-select-list
       [loading]="menuLoading"
       [data]="appMenusArr"
       [selected]="currentApp"
@@ -62,7 +62,7 @@
           <i nz-icon nzType="eye" nzTheme="outline"></i>
         </button>
       </ng-template>
-    </app-monitor-select-menu>
+    </app-monitor-select-list>
   </nz-sider>
   <nz-content style="display: flex; flex-direction: column">
     <app-toolbar wrapperStyle="margin: 8px 8px 4px 8px">
diff --git 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html
 
b/web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.html
similarity index 100%
copy from 
web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html
copy to 
web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.html
diff --git 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less
 
b/web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.less
similarity index 100%
copy from 
web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less
copy to 
web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.less
diff --git 
a/web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.spec.ts
 
b/web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.spec.ts
new file mode 100755
index 0000000000..fd903d3ed3
--- /dev/null
+++ 
b/web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.spec.ts
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MonitorSelectListComponent } from './monitor-select-list.component';
+
+describe('MonitorSelectListComponent', () => {
+  let component: MonitorSelectListComponent;
+  let fixture: ComponentFixture<MonitorSelectListComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [MonitorSelectListComponent]
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(MonitorSelectListComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts
 
b/web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.ts
similarity index 90%
copy from 
web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts
copy to 
web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.ts
index 20315dea20..31aef6f30d 100755
--- 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts
+++ 
b/web-app/src/app/shared/components/monitor-select-list/monitor-select-list.component.ts
@@ -20,11 +20,11 @@
 import { Component, ContentChild, EventEmitter, Input, Output, TemplateRef } 
from '@angular/core';
 
 @Component({
-  selector: 'app-monitor-select-menu',
-  templateUrl: './monitor-select-menu.component.html',
-  styleUrls: ['./monitor-select-menu.component.less']
+  selector: 'app-monitor-select-list',
+  templateUrl: './monitor-select-list.component.html',
+  styleUrls: ['./monitor-select-list.component.less']
 })
-export class MonitorSelectMenuComponent {
+export class MonitorSelectListComponent {
   @ContentChild('prefix', { static: true }) prefixTemplateRef: 
TemplateRef<any> | undefined;
   @ContentChild('suffix', { static: true }) suffixTemplateRef: 
TemplateRef<any> | undefined;
   @Input() data!: any[][];
diff --git 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html
 
b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html
index fd2c2b472f..44a7ddd46e 100755
--- 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html
+++ 
b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html
@@ -18,7 +18,7 @@
 -->
 
 <nz-spin [nzSpinning]="loading" style="height: 100%">
-  <div style="margin: 8px 8px -4px 8px">
+  <div class="search-container">
     <app-multi-func-input
       type="search"
       [placeholder]="searchPlaceholder || ('common.search' | i18n)"
@@ -26,22 +26,29 @@
       (valueChange)="filter($event)"
     />
   </div>
-  <nz-divider></nz-divider>
-  <ul [style]="'flex: 1; overflow: hidden; overflow-y: auto;' + listStyle" 
nz-menu nzMode="inline" nzInlineCollapsed="false">
-    <li *ngFor="let menuItem of !!search ? dataByFilter : data" nz-submenu 
[nzTitle]="menuItem[1].label" [nzOpen]="!!search">
-      <ul>
-        <li class="item" nz-menu-item *ngFor="let app of menuItem[1].child" 
[nzSelected]="app.value === selected">
-          <ng-container *ngIf="prefixTemplateRef; else noPrefixContent">
-            <ng-template [ngTemplateOutlet]="prefixTemplateRef" 
[ngTemplateOutletContext]="{ item: app }"></ng-template>
-          </ng-container>
-          <ng-template #noPrefixContent></ng-template>
-          <span class="label" [title]="app.label" 
(click)="onSelectedChanged(app.value)">{{ app.label }}</span>
-          <ng-container *ngIf="suffixTemplateRef; else noSuffixContent">
-            <ng-template [ngTemplateOutlet]="suffixTemplateRef" 
[ngTemplateOutletContext]="{ item: app }"></ng-template>
-          </ng-container>
-          <ng-template #noSuffixContent></ng-template>
-        </li>
-      </ul>
-    </li>
-  </ul>
+  <div class="category-container" [style]="listStyle">
+    <div class="category-section" *ngFor="let menuItem of !!search ? 
dataByFilter : data">
+      <div class="category-header">
+        <span>
+          <i nz-icon [nzType]="getCategoryIcon(menuItem[0])" 
nzTheme="outline"></i>
+        </span>
+        <span class="category-title">{{ menuItem[1].label }}</span>
+        <span class="category-count">{{ menuItem[1].child.length }}</span>
+      </div>
+      <div class="category-items">
+        <div
+          class="monitor-type-card"
+          *ngFor="let app of menuItem[1].child"
+          [class.selected]="app.value === selected"
+          (click)="onSelectedChanged(app.value)"
+        >
+          <span class="card-label">{{ app.label }}</span>
+        </div>
+      </div>
+    </div>
+    <div class="empty-state" *ngIf="(!!search ? dataByFilter : data)?.length 
=== 0">
+      <i nz-icon nzType="inbox" nzTheme="outline"></i>
+      <span>{{ 'common.no-data' | i18n }}</span>
+    </div>
+  </div>
 </nz-spin>
diff --git 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less
 
b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less
index a723c9414e..89e8fc707f 100755
--- 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less
+++ 
b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less
@@ -1,31 +1,154 @@
+@import '~src/styles/theme';
+
 :host ::ng-deep {
+  .ant-spin-container {
+    height: 100%;
+    display: flex;
+    overflow: hidden;
+    flex-direction: column;
+  }
+}
 
-  .item{
-    padding-left: 32px!important;
+:host {
+  display: block;
+  height: 100%;
 
-    .ant-menu-title-content {
-      gap: 8px;
-      display: flex;
-      align-items: center;
+  .search-container {
+    padding: 16px 16px 0 16px;
+  }
 
-      :first-child {
-        flex-shrink: 0;
-      }
+  .category-container {
+    flex: 1;
+    overflow-y: auto;
+    overflow-x: hidden;
+    padding: 16px;
+  }
 
-      .label {
-        flex: 1;
-        overflow: hidden;
-        white-space: nowrap;
-        text-overflow: ellipsis;
-      }
+  .category-section {
+    margin-bottom: 20px;
+
+    &:last-child {
+      margin-bottom: 0;
     }
   }
 
-  .ant-spin-container {
-    height: 100%;
+  .category-header {
     display: flex;
+    align-items: center;
+    gap: 10px;
+    margin-bottom: 12px;
+    padding-bottom: 10px;
+    border-bottom: 1px solid #f0f0f0;
+  }
+
+  .category-title {
+    font-size: 15px;
+    font-weight: 600;
+    color: #1f1f1f;
+  }
+
+  .category-count {
+    font-size: 12px;
+    color: #8c8c8c;
+    background: #f5f5f5;
+    padding: 2px 8px;
+    border-radius: 10px;
+    margin-left: auto;
+  }
+
+  .category-items {
+    display: grid;
+    grid-template-columns: repeat(5, 1fr);
+    gap: 10px;
+  }
+
+  .monitor-type-card {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 10px 12px;
+    background: #fafafa;
+    border: 1px solid #e8e8e8;
+    border-radius: 6px;
+    cursor: pointer;
+    transition: all 0.2s ease;
+    text-align: center;
+
+    &:hover {
+      border-color: @primary-color;
+      background: #e6f4ff;
+      transform: translateY(-1px);
+      box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15);
+    }
+
+    &.selected {
+      border-color: @primary-color;
+      background: #e6f4ff;
+      box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+    }
+  }
+
+  .card-label {
+    font-size: 13px;
+    color: #333;
     overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    line-height: 1.4;
+  }
+
+  .empty-state {
+    display: flex;
     flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 48px 0;
+    color: #8c8c8c;
+
+    i {
+      font-size: 48px;
+      margin-bottom: 12px;
+    }
   }
+}
+
+// Dark theme support
+[data-theme='dark'] {
+  :host {
+    .category-header {
+      border-bottom-color: #303030;
+    }
+
+    .category-title {
+      color: #d9d9d9;
+    }
+
+    .category-count {
+      background: #303030;
+      color: #a0a0a0;
+    }
+
+    .monitor-type-card {
+      background: #1f1f1f;
+      border-color: #303030;
 
+      &:hover {
+        border-color: @primary-color;
+        background: #111d2c;
+      }
+
+      &.selected {
+        border-color: @primary-color;
+        background: #111d2c;
+      }
+    }
+
+    .card-label {
+      color: #d9d9d9;
+    }
+
+    .empty-state {
+      color: #6c6c6c;
+    }
+  }
 }
diff --git 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts
 
b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts
index 20315dea20..89f42e3555 100755
--- 
a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts
+++ 
b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts
@@ -51,4 +51,25 @@ export class MonitorSelectMenuComponent {
   onSelectedChanged(selected: string) {
     this.selectedChanged.emit(selected);
   }
+
+  getCategoryIcon(category: string): string {
+    const iconMap: Record<string, string> = {
+      os: 'desktop',
+      webserver: 'global',
+      bigdata: 'cluster',
+      cache: 'database',
+      service: 'api',
+      server: 'hdd',
+      mid: 'deployment-unit',
+      db: 'database',
+      custom: 'tool',
+      llm: 'robot',
+      network: 'wifi',
+      cn: 'cloud-server',
+      cicd: 'branches',
+      auto: 'thunderbolt',
+      program: 'code'
+    };
+    return iconMap[category] || 'appstore';
+  }
 }
diff --git a/web-app/src/app/shared/shared.module.ts 
b/web-app/src/app/shared/shared.module.ts
index 0d499cddfb..e111363ddb 100644
--- a/web-app/src/app/shared/shared.module.ts
+++ b/web-app/src/app/shared/shared.module.ts
@@ -25,6 +25,7 @@ import { ConfigurableFieldComponent } from 
'./components/configurable-field/conf
 import { FormFieldComponent } from 
'./components/form-field/form-field.component';
 import { HelpMessageShowComponent } from 
'./components/help-message-show/help-message-show.component';
 import { LabelSelectorComponent } from 
'./components/label-selector/label-selector.component';
+import { MonitorSelectListComponent } from 
'./components/monitor-select-list/monitor-select-list.component';
 import { MonitorSelectMenuComponent } from 
'./components/monitor-select-menu/monitor-select-menu.component';
 import { MultiFuncInputComponent } from 
'./components/multi-func-input/multi-func-input.component';
 import { ToolbarComponent } from './components/toolbar/toolbar.component';
@@ -42,6 +43,7 @@ const COMPONENTS: Array<Type<void>> = [
   ConfigurableFieldComponent,
   FormFieldComponent,
   MonitorSelectMenuComponent,
+  MonitorSelectListComponent,
   LabelSelectorComponent
 ];
 const DIRECTIVES: Array<Type<void>> = [TimezonePipe, I18nElsePipe, 
ElapsedTimePipe];
diff --git a/web-app/src/assets/app-data.json b/web-app/src/assets/app-data.json
index b232d4fd00..c880a953fe 100644
--- a/web-app/src/assets/app-data.json
+++ b/web-app/src/assets/app-data.json
@@ -223,7 +223,7 @@
           "i18n": "menu.advanced.mcp-server",
           "icon": "anticon-compass",
           "target": "_blank",
-          "externalLink": 
"https://hertzbeat.apache.org/docs/help/mcp_sse_server";
+          "externalLink": "https://hertzbeat.apache.org/docs/help/mcp_server";
         },
         {
           "text": "status",


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to