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

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

commit bc399453abd9e8d5696ed050a38d63d1e9551220
Author: zqr10159 <[email protected]>
AuthorDate: Tue Jul 16 00:09:21 2024 +0800

    feat(bulletin): implement dynamic metric fields for bulletin components
    
    Refactor the bulletin component to support dynamic metric fields based on 
the response data. This changemodifies the HTML template and TypeScript logic 
to handle metric fields extraction and displaydynamically, improving the 
flexibility of the bulletin system.
    
    BREAKING CHANGE: The bulletin component now expects data in a new format 
that includes metric fields.
    Existing implementations may need to be updated to accommodate this change.
---
 .../common/entity/manager/bulletin/Bulletin.java   |   4 +
 .../entity/manager/bulletin/BulletinDto.java       |  10 +-
 .../manager/bulletin/BulletinMetricsData.java      |  32 ++++--
 .../common/entity/manager/bulletin/BulletinVo.java |   5 +
 .../manager/controller/BulletinController.java     |  96 +++++++++---------
 .../manager/service/impl/BulletinServiceImpl.java  |   2 +
 web-app/src/app/pojo/BulletinDefine.ts             |   1 +
 .../app/routes/bulletin/bulletin.component.html    | 110 ++++++++++++++-------
 .../src/app/routes/bulletin/bulletin.component.ts  |  95 ++++++++++--------
 web-app/src/app/service/bulletin-define.service.ts |   4 +
 web-app/src/assets/i18n/zh-CN.json                 |  12 +++
 11 files changed, 231 insertions(+), 140 deletions(-)

diff --git 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/Bulletin.java
 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/Bulletin.java
index 69f418d1e..57043a1ff 100644
--- 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/Bulletin.java
+++ 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/Bulletin.java
@@ -60,6 +60,9 @@ public class Bulletin {
     @Schema(description = "Bulletin ID", example = "1")
     private Long id;
 
+    @Schema(description = "Bulletin Name", example = "Bulletin1", accessMode = 
READ_WRITE)
+    private String name;
+
     @Schema(description = "Monitor ID", example = "1")
     @Column(name = "monitor_id")
     private Long monitorId;
@@ -69,6 +72,7 @@ public class Bulletin {
 
     @Schema(description = "Monitor Metrics", example = "[\"cpu\", \"memory\"]")
     @Convert(converter = JsonStringListAttributeConverter.class)
+    @Column(length = 4096)
     private List<String> metrics;
 
     @Schema(description = "Tags(status:success,env:prod)", example = "{name: 
key1, value: value1}",
diff --git 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinDto.java
 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinDto.java
index fae1037bb..dad6faa75 100644
--- 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinDto.java
+++ 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinDto.java
@@ -18,17 +18,17 @@
 
 package org.apache.hertzbeat.common.entity.manager.bulletin;
 
-import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.Size;
 import java.util.List;
 import lombok.Data;
-import org.apache.hertzbeat.common.entity.manager.Monitor;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
 
 @Data
 public class BulletinDto {
 
+    /**
+     * Bulletin name
+     */
+    private String name;
+
     /**
      * Monitor type eg: jvm, tomcat
      */
diff --git 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinMetricsData.java
 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinMetricsData.java
index bdc3230cf..f9903ae7a 100644
--- 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinMetricsData.java
+++ 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinMetricsData.java
@@ -26,8 +26,6 @@ import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import org.apache.hertzbeat.common.entity.dto.Field;
-import org.apache.hertzbeat.common.entity.dto.ValueRow;
 
 /**
  * Bulletin Metrics Data
@@ -39,6 +37,12 @@ import org.apache.hertzbeat.common.entity.dto.ValueRow;
 @Schema(description = "Bulletin Metrics Data")
 public class BulletinMetricsData {
 
+    @Schema(title = "Bulletin ID")
+    private Long id;
+
+    @Schema(title = "Bulletin Name")
+    private String name;
+
     @Schema(title = "Monitor Type")
     private String app;
 
@@ -51,7 +55,7 @@ public class BulletinMetricsData {
     @NoArgsConstructor
     public static class Content{
         @Schema(title = "Monitor ID")
-        private Long id;
+        private Long monitorId;
 
         @Schema(title = "Monitor IP")
         private String host;
@@ -66,16 +70,28 @@ public class BulletinMetricsData {
     @NoArgsConstructor
     @Schema(description = "Metrics Data")
     public static class Metric{
-        @Schema(title = "Metric type")
-        private String type;
 
-        @Schema(title = "Metric name")
+        @Schema(title = "Metric type")
         private String name;
 
-        @Schema(title = "Metric unit")
+        @Schema(title = "Metric fields")
+        private List<Field> fields;
+    }
+
+    @Data
+    @Builder
+    @AllArgsConstructor
+    @NoArgsConstructor
+    @Schema(description = "Metrics field")
+    public static class Field{
+
+        @Schema(title = "Field name")
+        private String key;
+
+        @Schema(title = "Field unit")
         private String unit;
 
-        @Schema(title = "Metric value")
+        @Schema(title = "Field value")
         private String value;
     }
 }
diff --git 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinVo.java
 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinVo.java
index c84a11b6e..e97ff3014 100644
--- 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinVo.java
+++ 
b/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinVo.java
@@ -37,6 +37,11 @@ public class BulletinVo {
      */
     private Long id;
 
+    /**
+     * Bulletin name
+     */
+    private String name;
+
     /**
      * Bulletin metrics
      */
diff --git 
a/manager/src/main/java/org/apache/hertzbeat/manager/controller/BulletinController.java
 
b/manager/src/main/java/org/apache/hertzbeat/manager/controller/BulletinController.java
index 6e58dedbb..27bb1e5cd 100644
--- 
a/manager/src/main/java/org/apache/hertzbeat/manager/controller/BulletinController.java
+++ 
b/manager/src/main/java/org/apache/hertzbeat/manager/controller/BulletinController.java
@@ -26,9 +26,7 @@ import jakarta.persistence.criteria.CriteriaBuilder;
 import jakarta.persistence.criteria.Predicate;
 import jakarta.validation.Valid;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -46,8 +44,8 @@ import 
org.apache.hertzbeat.common.entity.manager.bulletin.BulletinDto;
 import org.apache.hertzbeat.common.entity.manager.bulletin.BulletinMetricsData;
 import org.apache.hertzbeat.common.entity.manager.bulletin.BulletinVo;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
-import org.apache.hertzbeat.common.util.Pair;
 import org.apache.hertzbeat.manager.service.BulletinService;
+import org.apache.hertzbeat.manager.service.MonitorService;
 import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataReader;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
@@ -55,7 +53,6 @@ import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -78,6 +75,9 @@ public class BulletinController {
 
     @Autowired
     private RealTimeDataReader realTimeDataReader;
+
+    @Autowired
+    private MonitorService monitorService;
     /**
      * add a new bulletin
      */
@@ -136,7 +136,8 @@ public class BulletinController {
     }
 
     @GetMapping("/metrics/{id}")
-    @Operation(summary = "Query Bulletin Real Time Metrics Data", description 
= "Query Bulletin real-time metrics data of monitoring indicators")
+    @Operation(summary = "Query Bulletin Real Time Metrics Data",
+            description = "Query Bulletin real-time metrics data of monitoring 
indicators")
     public ResponseEntity<Message<List<MetricsData>>> getMetricsData(
             @Parameter(description = "Bulletin Id", example = 
"402372614668544")
             @PathVariable Long id) {
@@ -196,56 +197,51 @@ public class BulletinController {
             return ResponseEntity.ok(Message.fail(FAIL_CODE, "real time store 
not available"));
         }
         List<Bulletin> bulletinList = bulletinService.listBulletin();
-        List<BulletinMetricsData> dataList = new ArrayList<>();
+        List<BulletinMetricsData> da = new ArrayList<>();
         for (Bulletin bulletin : bulletinList) {
-            List<String> metricList = bulletin.getMetrics();
-            Map<String, CollectRep.MetricsData> metricsDataMap = 
metricList.stream()
-                    .collect(Collectors.toMap(
-                            metric -> metric,
-                            metric -> metric.split("-")[0],
-                            (existing, replacement) -> existing
-                    ))
-                    .values().stream()
-                    .distinct()
-                    .collect(Collectors.toMap(
-                            metric -> metric,
-                            metric -> 
realTimeDataReader.getCurrentMetricsData(bulletin.getMonitorId(), metric)
-                    ));
-
-
-
-            for (Map.Entry<String, CollectRep.MetricsData> entry : 
metricsDataMap.entrySet()) {
-                CollectRep.MetricsData storageData = entry.getValue();
-
-                BulletinMetricsData.BulletinMetricsDataBuilder dataBuilder = 
BulletinMetricsData.builder();
-                dataBuilder.app(storageData.getApp());
-
-                BulletinMetricsData.Content.ContentBuilder contentBuilder = 
BulletinMetricsData.Content.builder();
-                BulletinMetricsData.Metric.MetricBuilder metricBuilder = 
BulletinMetricsData.Metric.builder();
-
-                contentBuilder.id(storageData.getId());
-
-                List<BulletinMetricsData.Metric> metrics = 
storageData.getFieldsList().stream()
-                        .map(tmpField -> metricBuilder
-                                .type(entry.getKey().split("-")[0])
-                                .name(tmpField.getName())
-                                .unit(tmpField.getUnit())
-                                .build())
-                        .collect(Collectors.toList());
-
-                for (CollectRep.ValueRow valueRow : 
storageData.getValuesList()) {
-                    for (int i = 0; i < metrics.size(); i++) {
-                        BulletinMetricsData.Metric metric = metrics.get(i);
+            BulletinMetricsData.BulletinMetricsDataBuilder dataBuilder = 
BulletinMetricsData.builder();
+            
dataBuilder.id(bulletin.getId()).name(bulletin.getName()).app(bulletin.getApp());
+
+            BulletinMetricsData.Content.ContentBuilder contentBuilder = 
BulletinMetricsData.Content.builder();
+            
contentBuilder.monitorId(bulletin.getMonitorId()).host(monitorService.getMonitor(bulletin.getMonitorId()).getHost());
+
+            BulletinMetricsData.Metric.MetricBuilder metricBuilder = 
BulletinMetricsData.Metric.builder();
+            List<BulletinMetricsData.Metric> metrics = new ArrayList<>();
+            for (String metric : bulletin.getMetrics()) {
+                metricBuilder.name(metric.split("-")[0]);
+                List<BulletinMetricsData.Field> fields = new ArrayList<>();
+                CollectRep.MetricsData currentMetricsData = 
realTimeDataReader.getCurrentMetricsData(bulletin.getMonitorId(), 
metric.split("-")[0]);
+
+                for (CollectRep.Field field : 
currentMetricsData.getFieldsList()) {
+                    
fields.add(BulletinMetricsData.Field.builder().key(field.getName()).unit(field.getUnit()).build());
+                }
+
+                List<CollectRep.ValueRow> valuesList = 
currentMetricsData.getValuesList();
+                List<BulletinMetricsData.Field> metricFields = new 
ArrayList<>();
+                for (CollectRep.ValueRow valueRow : valuesList) {
+                    for (int i = 0; i < fields.size(); i++) {
+                        CollectRep.Field field = 
currentMetricsData.getFieldsList().get(i);
                         String origin = valueRow.getColumns(i);
-                        metric.setValue(origin);
+                        BulletinMetricsData.Field metricField = 
BulletinMetricsData.Field.builder()
+                                .key(field.getName())
+                                .unit(field.getUnit())
+                                .value(origin)
+                                .build();
+                        metricFields.add(metricField);
                     }
                 }
-                contentBuilder.metrics(metrics);
-                BulletinMetricsData bulletinMetricsData = 
dataBuilder.content(contentBuilder.build()).build();
-                dataList.add(bulletinMetricsData);
+                metricBuilder.fields(metricFields);
+                metrics.add(metricBuilder.build());
             }
+            contentBuilder.metrics(metrics);
+            dataBuilder.content(contentBuilder.build());
+            da.add(dataBuilder.build());
+        }
+
+        return ResponseEntity.ok(Message.success(da));
     }
-        return ResponseEntity.ok(Message.success(dataList));
-    }
+
+
+
 
 }
diff --git 
a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/BulletinServiceImpl.java
 
b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/BulletinServiceImpl.java
index db93d68b9..f1fa46b92 100644
--- 
a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/BulletinServiceImpl.java
+++ 
b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/BulletinServiceImpl.java
@@ -93,6 +93,7 @@ public class BulletinServiceImpl implements BulletinService {
         try {
             List<Bulletin> bulletins = 
bulletinDto.getMonitorIds().stream().map(monitorId -> {
                 Bulletin bulletin = new Bulletin();
+                bulletin.setName(bulletinDto.getName());
                 bulletin.setId(SnowFlakeIdGenerator.generateId());
                 bulletin.setMetrics(bulletinDto.getMetrics());
                 bulletin.setMonitorId(monitorId);
@@ -122,6 +123,7 @@ public class BulletinServiceImpl implements BulletinService 
{
             voList = bulletinPage.stream().map(bulletin -> {
                 BulletinVo vo = new BulletinVo();
                 vo.setId(bulletin.getId());
+                vo.setName(bulletin.getName());
                 vo.setTags(bulletin.getTags());
                 vo.setMetrics(bulletin.getMetrics());
                 vo.setMonitorId(bulletin.getMonitorId());
diff --git a/web-app/src/app/pojo/BulletinDefine.ts 
b/web-app/src/app/pojo/BulletinDefine.ts
index 16a2396c7..817b28d66 100644
--- a/web-app/src/app/pojo/BulletinDefine.ts
+++ b/web-app/src/app/pojo/BulletinDefine.ts
@@ -22,6 +22,7 @@ import {TagItem} from "./NoticeRule";
 
 export class BulletinDefine {
   id!: number;
+  name!: string;
   monitorIds!: number[];
   app!: string;
   metrics!: string[];
diff --git a/web-app/src/app/routes/bulletin/bulletin.component.html 
b/web-app/src/app/routes/bulletin/bulletin.component.html
index 44d82ddc2..aadc78301 100644
--- a/web-app/src/app/routes/bulletin/bulletin.component.html
+++ b/web-app/src/app/routes/bulletin/bulletin.component.html
@@ -43,39 +43,59 @@
 </app-toolbar>
 
 <nz-tabset nzType="card">
-  <nz-tab *ngFor="let d of this.tabDefines" [nzTitle]="d.app">
+  <nz-tab *ngFor="let bulletinTab of tabDefines" [nzTitle]="bulletinTab.name">
     <nz-table
-      *ngIf="d.app === this.app"
+      *ngIf="bulletinTab.data.length"
       #fixedTable
-      [nzData]="listOfData"
-      [nzPageIndex]="pageIndex"
-      [nzPageSize]="pageSize"
-      [nzTotal]="total"
+      [nzData]="bulletinTab.data.slice((bulletinTab.pageIndex - 1) * 
bulletinTab.pageSize, bulletinTab.pageIndex * bulletinTab.pageSize)"
+      [nzPageIndex]="bulletinTab.pageIndex"
+      [nzPageSize]="bulletinTab.pageSize"
+      [nzTotal]="bulletinTab.total"
       nzFrontPagination="false"
       [nzLoading]="tableLoading"
       nzShowSizeChanger
       [nzShowTotal]="rangeTemplate"
-      [nzPageSizeOptions]="[8, 15, 25]"
+      [nzPageSizeOptions]="[10, 20, 50, 100]"
       (nzQueryParams)="onTablePageChange($event)"
       nzShowPagination="true"
-      [nzScroll]="{ x: '1240px' }"
+      [nzScroll]="{ x: '+' +
+       'auto' }"
+      nzBordered
     >
       <thead>
-        <tr>
-          <th nzAlign="center" nzLeft nzWidth="3%" [(nzChecked)]="checkedAll" 
(nzCheckedChange)="onAllChecked($event)"></th>
-          <ng-container *ngFor="let column of listOfColumns">
-            <th>{{ column.title }}</th>
+      <tr>
+        <th nzAlign="center" nzLeft nzWidth="3%" rowspan="2">
+          <label nz-checkbox [(ngModel)]="checkedAll" 
(ngModelChange)="onAllChecked($event)"></label>
+        </th>
+        <th nzAlign="center" nzWidth="7%" rowspan="2">App</th>
+        <th nzAlign="center" nzWidth="7%" rowspan="2">Host</th>
+        <ng-container *ngFor="let metricName of getMetricNames(bulletinTab)">
+          <th nzAlign="center" 
[colSpan]="bulletinTab.bulletinColumn[metricName].size">{{ metricName }}</th>
+        </ng-container>
+      </tr>
+      <tr>
+        <ng-container *ngFor="let metricName of getMetricNames(bulletinTab)">
+          <ng-container *ngFor="let field of 
bulletinTab.bulletinColumn[metricName]">
+            <th nzAlign="center">{{ field }}</th>
           </ng-container>
-          <th nzAlign="center" nzWidth="15%">{{ 'common.edit' | i18n }}</th>
-        </tr>
+        </ng-container>
+        <th nzAlign="center" nzWidth="15%" rowspan="2">{{ 'common.edit' | i18n 
}}</th>
+      </tr>
       </thead>
       <tbody>
-        <tr *ngFor="let data of fixedTable.data">
-          <td nzAlign="center" nzLeft 
[nzChecked]="checkedDefineIds.has(data.id)" 
(nzCheckedChange)="onItemChecked(data.id, $event)"></td>
-          <ng-container *ngFor="let column of listOfColumns">
-            <td>{{ data[column.key] }}</td>
+      <tr *ngFor="let data of fixedTable.data">
+        <td nzAlign="center" nzLeft>
+          <label nz-checkbox [ngModel]="checkedDefineIds.has(data.id)" 
(ngModelChange)="onItemChecked(data.id, $event)"></label>
+        </td>
+        <td nzAlign="center">{{ data.app }}</td>
+        <td nzAlign="center">{{ data.host }}</td>
+        <ng-container *ngFor="let metricName of getMetricNames(bulletinTab)">
+          <ng-container *ngFor="let field of 
bulletinTab.bulletinColumn[metricName]">
+            <td nzAlign="center">{{ data[metricName + '_' + field] }}</td>
           </ng-container>
-          <td nzAlign="center">
+        </ng-container>
+        <td nzAlign="center">
+          <div style="display: flex; justify-content: center; gap: 8px;">
             <button
               nz-button
               nzType="primary"
@@ -95,17 +115,29 @@
             >
               <i nz-icon nzType="delete" nzTheme="outline"></i>
             </button>
-          </td>
-          <ng-container *ngFor="let metric of d.metrics">
-            <td nzAlign="center"></td>
-          </ng-container>
-        </tr>
+          </div>
+        </td>
+      </tr>
       </tbody>
     </nz-table>
-    <ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }} 
</ng-template>
+
+    <ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ 
bulletinTab.total }} </ng-template>
   </nz-tab>
 </nz-tabset>
 
+
+
+
+
+
+
+
+
+
+
+
+
+
 <!-- new bulletin modal -->
 <nz-modal
   [(nzVisible)]="isManageModalVisible"
@@ -119,7 +151,14 @@
   <div *nzModalContent class="-inner-content">
     <form nz-form #defineForm="ngForm">
       <nz-form-item>
-        <nz-form-label [nzSpan]="7" nzFor="dropdown" nzRequired="true">{{ 
'dropdown.label' | i18n }}</nz-form-label>
+        <nz-form-label [nzSpan]="7" nzFor="textInput" nzRequired="true">{{ 
'bulletin.name' | i18n }}</nz-form-label>
+        <nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | 
i18n">
+          <input nz-input placeholder="{{ 'bulletin.name.placeholder' | i18n 
}}" [(ngModel)]="define.name" name="inputText" required />
+        </nz-form-control>
+      </nz-form-item>
+
+      <nz-form-item>
+        <nz-form-label [nzSpan]="7" nzFor="dropdown" nzRequired="true">{{ 
'bulletin.monitor.type' | i18n }}</nz-form-label>
         <nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | 
i18n">
           <nz-select
             nzAllowClear
@@ -135,8 +174,9 @@
           </nz-select>
         </nz-form-control>
       </nz-form-item>
+
       <nz-form-item>
-        <nz-form-label [nzSpan]="7" nzFor="dropdown" nzRequired="true">{{ 
'dropdown.label' | i18n }}</nz-form-label>
+        <nz-form-label [nzSpan]="7" nzFor="dropdown" nzRequired="true">{{ 
'bulletin.monitor.name' | i18n }}</nz-form-label>
         <nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | 
i18n">
           <nz-select
             nzAllowClear
@@ -152,8 +192,9 @@
           </nz-select>
         </nz-form-control>
       </nz-form-item>
+
       <nz-form-item>
-        <nz-form-label [nzSpan]="7" nzFor="dropdown" nzRequired="true">{{ 
'dropdown.label' | i18n }}</nz-form-label>
+        <nz-form-label [nzSpan]="7" nzFor="dropdown" nzRequired="true">{{ 
'bulletin.monitor.metrics' | i18n }}</nz-form-label>
         <nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | 
i18n">
           <nz-transfer
             [nzDataSource]="hierarchies"
@@ -173,12 +214,12 @@
                 (nzCheckBoxChange)="treeCheckBoxChange($event, onItemSelect)"
               >
                 <ng-template let-node>
-                  <span
-                    (click)="checkBoxChange(node, onItemSelect)"
-                    class="ant-tree-node-content-wrapper 
ant-tree-node-content-wrapper-open"
-                  >
-                    {{ node.title }}
-                  </span>
+                <span
+                  (click)="checkBoxChange(node, onItemSelect)"
+                  class="ant-tree-node-content-wrapper 
ant-tree-node-content-wrapper-open"
+                >
+                  {{ node.title }}
+                </span>
                 </ng-template>
               </nz-tree>
             </ng-template>
@@ -187,4 +228,3 @@
       </nz-form-item>
     </form>
   </div>
-</nz-modal>
diff --git a/web-app/src/app/routes/bulletin/bulletin.component.ts 
b/web-app/src/app/routes/bulletin/bulletin.component.ts
index e76ffe4a5..a8ddf032e 100644
--- a/web-app/src/app/routes/bulletin/bulletin.component.ts
+++ b/web-app/src/app/routes/bulletin/bulletin.component.ts
@@ -38,6 +38,7 @@ import { AppDefineService } from 
'../../service/app-define.service';
 import { BulletinDefineService } from '../../service/bulletin-define.service';
 import { MonitorService } from '../../service/monitor.service';
 import { TagService } from '../../service/tag.service';
+import {$} from "protractor";
 
 @Component({
   selector: 'app-bulletin',
@@ -60,7 +61,7 @@ export class BulletinComponent implements OnInit {
   pageSize: number = 8;
   total: number = 0;
   defines!: BulletinDefine[];
-  tabDefines!: BulletinDefine[];
+  tabDefines!: any[];
   tableLoading: boolean = true;
   checkedDefineIds = new Set<number>();
   isSwitchExportTypeModalVisible = false;
@@ -73,25 +74,15 @@ export class BulletinComponent implements OnInit {
   checkedNodeList: NzTreeNode[] = [];
   monitors: Monitor[] = [];
   loading: boolean = false;
-  listOfData: any[] = [];
-  listOfColumns: Array<{ key: string; title: string }> = [];
-  responseData: any[] = [];
-  metrics: string[] = [];
-
-  id: any;
-  app: any;
-  metric: any;
-  fields: any;
-  valueRows: any;
+  rawData: any[] = [];
+
   ngOnInit(): void {
     this.loadBulletinDefineTable();
-    this.tabDefines = this.defines;
-    this.loadData(402372614668544);
+    this.loadData();
   }
 
   sync() {
     this.loadBulletinDefineTable();
-    this.tabDefines = this.defines;
   }
 
   loadBulletinDefineTable() {
@@ -656,41 +647,58 @@ export class BulletinComponent implements OnInit {
     });
   }
 
-  loadData(bulletinId: number) {
+  loadData() {
     this.loading = true;
-    let metricData$ = this.bulletinDefineSvc
-      .getMonitorMetricsData(bulletinId)
+    const metricData$ = this.bulletinDefineSvc
+      .getAllMonitorMetricsData()
       .pipe(finalize(() => (this.loading = false)))
       .subscribe(
         message => {
           metricData$.unsubscribe();
           if (message.code === 0 && message.data) {
-            this.responseData = message.data;
-            this.responseData.forEach((item: any) => {
-              const { id, app, metrics, fields, valueRows } = message.data;
-              this.id = id;
-              this.app = app;
-              this.metric = metrics;
-              this.fields = fields;
-              this.valueRows = valueRows;
-
-              this.listOfColumns.push(
-                fields.map((field: { name: string; unit: any }) => ({
-                  key: field.name,
-                  title: field.name.toUpperCase() + (field.unit ? ` 
(${field.unit})` : '')
-                }))
-              );
-
-              this.listOfData.push(
-                valueRows.map((row: { labels: any; values: any[] }) => {
-                  const rowData: any = { ...row.labels };
-                  row.values.forEach((value, index) => {
-                    rowData[fields[index].name] = value.origin;
-                  });
-                  return rowData;
-                })
-              );
+            this.rawData = message.data;
+            const groupedData: any = {};
+
+            this.rawData.forEach(item => {
+              const name = item.name;
+              if (!groupedData[name]) {
+                groupedData[name] = {
+                  bulletinColumn: {},
+                  data: []
+                };
+              }
+
+              const transformedItem: any = {
+                id: item.id,
+                app: item.app,
+                monitorId: item.content.monitorId,
+                host: item.content.host
+              };
+
+              item.content.metrics.forEach((metric: { name: string | number; 
fields: { key: any; value: any; }[]; }) => {
+                if (!groupedData[name].bulletinColumn[metric.name]) {
+                  groupedData[name].bulletinColumn[metric.name] = new 
Set<string>();
+                }
+                metric.fields.forEach((field: { key: any; value: any; }) => {
+                  const key = `${metric.name}_${field.key}`;
+                  transformedItem[key] = field.value;
+                  groupedData[name].bulletinColumn[metric.name].add(field.key);
+                });
+              });
+
+              groupedData[name].data.push(transformedItem);
             });
+            console.log(groupedData);
+
+            this.tabDefines = Object.keys(groupedData).map(name => ({
+              name,
+              bulletinColumn: groupedData[name].bulletinColumn,
+              data: groupedData[name].data,
+              pageIndex: 1,
+              pageSize: 10,
+              total: groupedData[name].data.length
+            }));
+            console.log(this.tabDefines);
 
           } else if (message.code !== 0) {
             this.notifySvc.warning(`${message.msg}`, '');
@@ -703,4 +711,7 @@ export class BulletinComponent implements OnInit {
         }
       );
   }
+  getMetricNames(bulletinTab: any): string[] {
+    return Object.keys(bulletinTab.bulletinColumn);
+  }
 }
diff --git a/web-app/src/app/service/bulletin-define.service.ts 
b/web-app/src/app/service/bulletin-define.service.ts
index 93a3b4342..019144de8 100644
--- a/web-app/src/app/service/bulletin-define.service.ts
+++ b/web-app/src/app/service/bulletin-define.service.ts
@@ -83,5 +83,9 @@ export class BulletinDefineService {
     return 
this.http.get<Message<any>>(`${bulletin_define_uri}/metrics/${bulletinId}`);
   }
 
+  public getAllMonitorMetricsData(): Observable<Message<any>> {
+    return this.http.get<Message<any>>(`${bulletin_define_uri}/metrics`);
+  }
+
 
 }
diff --git a/web-app/src/assets/i18n/zh-CN.json 
b/web-app/src/assets/i18n/zh-CN.json
index 37db59664..3bec1bb01 100644
--- a/web-app/src/assets/i18n/zh-CN.json
+++ b/web-app/src/assets/i18n/zh-CN.json
@@ -130,6 +130,18 @@
       "2": "警告告警"
     }
   },
+  "bulletin": {
+    "name": "看板名称",
+    "name.placeholder": "请输入自定义看板名称",
+    "monitor.type": "监控类型",
+    "monitor.name": "监控任务名称",
+    "monitor.metrics": "监控指标",
+    "content": "公告内容",
+    "time": "发布时间",
+    "status": "状态",
+    "status.online": "已发布",
+    "status.offline": "未发布"
+  },
   "question.link": "https://hertzbeat.apache.org/zh-cn/docs/help/issue";,
   "alert.setting.new": "新增阈值规则",
   "alert.setting.edit": "编辑阈值规则",


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

Reply via email to