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

zhaoqingran 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 a34ccdd76 [improve] refactor bulletin impl code (#2714)
a34ccdd76 is described below

commit a34ccdd76976b9a2b372425e0677d5dc87a3b6c0
Author: tomsun28 <[email protected]>
AuthorDate: Sun Sep 15 00:41:18 2024 +0800

    [improve] refactor bulletin impl code (#2714)
    
    Signed-off-by: tomsun28 <[email protected]>
---
 README.md                                          |  19 ---
 README_CN.md                                       |  19 ---
 .../entity/manager/{bulletin => }/Bulletin.java    |  17 +--
 ...Dto.java => JsonMapListAttributeConverter.java} |  49 +++----
 .../common/entity/manager/bulletin/BulletinVo.java |  65 ---------
 home/static/img/home/1.png                         | Bin 1415895 -> 1421873 
bytes
 home/static/img/home/2.png                         | Bin 1278829 -> 1261602 
bytes
 .../manager/controller/BulletinController.java     |  85 ++++--------
 .../apache/hertzbeat/manager/dao/BulletinDao.java  |   2 +-
 .../manager/pojo/dto}/BulletinMetricsData.java     |   2 +-
 .../hertzbeat/manager/service/BulletinService.java |  54 +++-----
 .../manager/service/impl/BulletinServiceImpl.java  | 150 +++++++--------------
 .../manager/controller/BulletinControllerTest.java |  71 ++--------
 .../manager/service/BulletinServiceTest.java       |  70 ++--------
 .../app/routes/bulletin/bulletin.component.html    |  22 +--
 .../src/app/routes/bulletin/bulletin.component.ts  | 121 ++++++++---------
 web-app/src/app/service/bulletin-define.service.ts |  36 +----
 web-app/src/assets/i18n/en-US.json                 |  22 +--
 18 files changed, 226 insertions(+), 578 deletions(-)

diff --git a/README.md b/README.md
index e3dbb3ae3..ad96c1117 100644
--- a/README.md
+++ b/README.md
@@ -180,10 +180,6 @@ Detailed steps refer to [Artifact 
Hub](https://artifacthub.io/packages/helm/hert
 
 **HAVE FUN**
 
-## 🥐 Roadmap
-
-![hertzBeat](home/static/img/docs/hertzbeat-roadmap.png) 
-
 ## ✨ Contributors
 
 Thanks to these wonderful people, welcome to join us:     
@@ -525,20 +521,5 @@ HertzBeat has been included in the <a 
href="https://landscape.cncf.io/guide?item
 CNCF Observability And Analysis - Monitoring Landscape.</a>
 </p>
 
-
-## Star History
-
-[![Star History 
Chart](https://api.star-history.com/svg?repos=apache/hertzbeat&type=Date)](https://star-history.com/#apache/hertzbeat&Date)
-
-## Contributors
-
-### Monthly Active Contributors
-
-[![Monthly Active 
Contributors](https://contributor-overtime-api.git-contributor.com/contributors-svg?chart=contributorMonthlyActivity&repo=apache/hertzbeat)](https://git-contributor.com?chart=contributorMonthlyActivity&repo=apache/hertzbeat)
-
-### GitHub Contributor Over Time
-
-[![GitHub Contributor Over 
Time](https://contributor-overtime-api.git-contributor.com/contributors-svg?chart=contributorOverTime&repo=apache/hertzbeat)](https://git-contributor.com?chart=contributorOverTime&repo=apache/hertzbeat)
-
 ## 🛡️ License
 [`Apache License, Version 
2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)
diff --git a/README_CN.md b/README_CN.md
index ffa5ae0ac..24daaa307 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -179,10 +179,6 @@
 
 **HAVE FUN**
 
-## 🥐 路线图
-
-![hertzBeat](home/static/img/docs/hertzbeat-roadmap.png)
-
 ## ✨ Contributors
 
 Thanks these wonderful people, welcome to join us:   
@@ -526,20 +522,5 @@ HertzBeat has been included in the <a 
href="https://landscape.cncf.io/guide?item
 CNCF Observability And Analysis - Monitoring Landscape.</a>
 </p>
 
-
-## Star History
-
-[![Star History 
Chart](https://api.star-history.com/svg?repos=apache/hertzbeat&type=Date)](https://star-history.com/#apache/hertzbeat&Date)
-
-## Contributors
-
-### Monthly Active Contributors
-
-[![Monthly Active 
Contributors](https://contributor-overtime-api.git-contributor.com/contributors-svg?chart=contributorMonthlyActivity&repo=apache/hertzbeat)](https://git-contributor.com?chart=contributorMonthlyActivity&repo=apache/hertzbeat)
-
-### GitHub Contributor Over Time
-
-[![GitHub Contributor Over 
Time](https://contributor-overtime-api.git-contributor.com/contributors-svg?chart=contributorOverTime&repo=apache/hertzbeat)](https://git-contributor.com?chart=contributorOverTime&repo=apache/hertzbeat)
-
 ## 🛡️ License
 [`Apache License, Version 
2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)
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.java
similarity index 88%
rename from 
common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/Bulletin.java
rename to 
common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
index 60e1d87be..b0d724dd8 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.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.common.entity.manager.bulletin;
+package org.apache.hertzbeat.common.entity.manager;
 
 import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -23,17 +23,17 @@ import jakarta.persistence.Column;
 import jakarta.persistence.Convert;
 import jakarta.persistence.Entity;
 import jakarta.persistence.EntityListeners;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
 import jakarta.persistence.Table;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import 
org.apache.hertzbeat.common.entity.manager.JsonLongListAttributeConverter;
-import 
org.apache.hertzbeat.common.entity.manager.JsonTagListAttributeConverter;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
 import org.springframework.data.annotation.CreatedBy;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.annotation.LastModifiedBy;
@@ -54,6 +54,7 @@ import 
org.springframework.data.jpa.domain.support.AuditingEntityListener;
 public class Bulletin {
 
     @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Schema(description = "Bulletin ID", example = "1")
     private Long id;
 
@@ -61,17 +62,17 @@ public class Bulletin {
     private String name;
 
     @Schema(description = "Monitor IDs", example = "1")
-    @Column(name = "monitor_ids", length = 5000)
+    @Column(name = "monitor_ids", length = 4096)
     @Convert(converter = JsonLongListAttributeConverter.class)
     private List<Long> monitorIds;
 
     @Schema(description = "Monitor Type eg: jvm, tomcat", example = "jvm", 
accessMode = READ_WRITE)
     private String app;
 
-
     @Schema(description = "Monitor Fields")
-    @Column(length = 4096)
-    private String fields;
+    @Column(name = "fields", length = 4096)
+    @Convert(converter = JsonMapListAttributeConverter.class)
+    private Map<String, List<String>> fields;
 
     @Schema(description = "Tags(status:success,env:prod)", example = "{name: 
key1, value: value1}",
             accessMode = READ_WRITE)
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/JsonMapListAttributeConverter.java
similarity index 50%
rename from 
common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinDto.java
rename to 
common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonMapListAttributeConverter.java
index f077fd726..4a9a0530e 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/JsonMapListAttributeConverter.java
@@ -15,38 +15,31 @@
  * limitations under the License.
  */
 
+package org.apache.hertzbeat.common.entity.manager;
 
-package org.apache.hertzbeat.common.entity.manager.bulletin;
-
+import com.fasterxml.jackson.core.type.TypeReference;
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
 import java.util.List;
 import java.util.Map;
-import lombok.Data;
+import org.apache.hertzbeat.common.util.JsonUtil;
+import org.springframework.stereotype.Component;
 
 /**
- * Bulletin DTO
+ * json map list str converter
  */
-@Data
-public class BulletinDto {
-
-    /**
-     * Bulletin name
-     */
-    private String name;
-
-    /**
-     * Monitor type eg: jvm, tomcat
-     */
-    private String app;
-
-
-    /**
-     * Monitor fields
-     */
-    private Map<String, List<String>> fields;
-
-    /**
-     * Monitor ids
-     */
-    private List<Long> monitorIds;
-
+@Converter
+@Component
+public class JsonMapListAttributeConverter implements 
AttributeConverter<Map<String, List<String>>, String> {
+
+    @Override
+    public String convertToDatabaseColumn(Map<String, List<String>> attribute) 
{
+        return JsonUtil.toJson(attribute);
+    }
+
+    @Override
+    public Map<String, List<String>> convertToEntityAttribute(String dbData) {
+        TypeReference<Map<String, List<String>>> typeReference = new 
TypeReference<>() {};
+        return JsonUtil.fromJson(dbData, typeReference);
+    }
 }
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
deleted file mode 100644
index a49fbb18a..000000000
--- 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinVo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.hertzbeat.common.entity.manager.bulletin;
-
-import java.util.List;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
-
-/**
- * Bulletin Vo
- */
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class BulletinVo {
-
-    /**
-     * Bulletin ID
-     */
-    private Long id;
-
-    /**
-     * Bulletin name
-     */
-    private String name;
-
-    /**
-     * Bulletin metrics
-     */
-    private List<String> metrics;
-
-    /**
-     * Bulletin tags
-     */
-    private List<TagItem> tags;
-
-    /**
-     * Bulletin monitor ID
-     */
-    private List<Long> monitorId;
-
-    /**
-     * Bulletin monitor name
-     */
-    private String app;
-
-}
diff --git a/home/static/img/home/1.png b/home/static/img/home/1.png
index 60da22862..455c83a00 100644
Binary files a/home/static/img/home/1.png and b/home/static/img/home/1.png 
differ
diff --git a/home/static/img/home/2.png b/home/static/img/home/2.png
index e121b33fa..8e2bab7cb 100644
Binary files a/home/static/img/home/2.png and b/home/static/img/home/2.png 
differ
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 9769de88d..3c8bddf6c 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,13 +26,13 @@ import jakarta.validation.Valid;
 import java.util.List;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.common.entity.dto.Message;
-import org.apache.hertzbeat.common.entity.manager.bulletin.Bulletin;
-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;
+import org.apache.hertzbeat.manager.pojo.dto.BulletinMetricsData;
 import org.apache.hertzbeat.common.util.ResponseUtil;
 import org.apache.hertzbeat.manager.service.BulletinService;
 import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataReader;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -58,86 +58,59 @@ public class BulletinController {
     @Autowired
     private RealTimeDataReader realTimeDataReader;
 
-    /**
-     * add a new bulletin
-     */
+    @Operation(summary = "New a bulletin", description = "Add new bulletin")
     @PostMapping
-    public ResponseEntity<Message<Void>> addNewBulletin(@Valid @RequestBody 
BulletinDto bulletinDto) {
+    public ResponseEntity<Message<Void>> addNewBulletin(@Valid @RequestBody 
Bulletin bulletin) {
         try {
-            bulletinService.validate(bulletinDto);
-            bulletinService.addBulletin(bulletinDto);
+            bulletinService.validate(bulletin);
+            bulletinService.addBulletin(bulletin);
         } catch (Exception e) {
             return ResponseEntity.ok(Message.fail(FAIL_CODE, "Add failed! " + 
e.getMessage()));
         }
         return ResponseEntity.ok(Message.success("Add success!"));
     }
 
-    /**
-     * edit a exist bulletin
-     */
+    @Operation(summary = "Update a bulletin", description = "Update the 
bulletin")
     @PutMapping
-    public ResponseEntity<Message<Void>> editBulletin(@Valid @RequestBody 
BulletinDto bulletinDto) {
+    public ResponseEntity<Message<Void>> editBulletin(@Valid @RequestBody 
Bulletin bulletin) {
         try {
-            bulletinService.validate(bulletinDto);
-            bulletinService.editBulletin(bulletinDto);
+            bulletinService.validate(bulletin);
+            bulletinService.editBulletin(bulletin);
         } catch (Exception e) {
             return ResponseEntity.ok(Message.fail(FAIL_CODE, "Edit failed! " + 
e.getMessage()));
         }
         return ResponseEntity.ok(Message.success("Add success!"));
     }
 
-    /**
-     * edit a exist bulletin
-     */
-    @GetMapping("/{name}")
-    public ResponseEntity<Message<Bulletin>> getBulletinByName(@Valid 
@PathVariable String name) {
-        try {
-            return 
ResponseEntity.ok(Message.success(bulletinService.getBulletinByName(name)));
-        } catch (Exception e) {
-            return ResponseEntity.ok(Message.fail(FAIL_CODE, "Get failed! " + 
e.getMessage()));
-        }
+    @Operation(summary = "Query One Bulletin", description = "Query One 
Bulletin")
+    @GetMapping("/{id}")
+    public ResponseEntity<Message<Bulletin>> getBulletin(@Valid @PathVariable 
Long id) {
+        return 
ResponseEntity.ok(Message.success(bulletinService.getBulletinById(id).orElse(null)));
     }
-
-    /**
-     * get All Names
-     */
-    @Operation(summary = "Get All Bulletin Names", description = "Get All 
Bulletin Names")
-    @GetMapping("/names")
-    public ResponseEntity<Message<List<String>>> getAllNames() {
-        return ResponseUtil.handle(() -> bulletinService.getAllNames());
+    
+    @Operation(summary = "Query Bulletins", description = "Query All Bulletin")
+    @GetMapping
+    public ResponseEntity<Message<Page<Bulletin>>> queryBulletins(
+            @Parameter(description = "Search", example = "tom") 
@RequestParam(required = false) final String search,
+            @Parameter(description = "List current page", example = "0") 
@RequestParam(defaultValue = "0") Integer pageIndex,
+            @Parameter(description = "Number of list pagination", example = 
"8") @RequestParam(required = false) Integer pageSize) {
+        return ResponseUtil.handle(() -> bulletinService.getBulletins(search, 
pageIndex, pageSize));
     }
-
-    /**
-     * delete bulletin by name
-     */
-    @Operation(summary = "Delete Bulletin by Name", description = "Delete 
Bulletin by Name")
+    
+    @Operation(summary = "Delete Bulletins", description = "Delete Bulletin by 
ids")
     @DeleteMapping
-    public ResponseEntity<Message<Void>> deleteBulletin(
-            @Parameter(description = "Bulletin Name", example = 
"402372614668544")
-            @RequestParam List<String> names) {
-        try {
-            bulletinService.deleteBulletinByName(names);
-        } catch (Exception e) {
-            return ResponseEntity.ok(Message.fail(FAIL_CODE, "Delete failed!" 
+ e.getMessage()));
-        }
+    public ResponseEntity<Message<Void>> deleteBulletin(@Parameter(description 
= "Bulletin ids") @RequestParam List<Long> ids) {
+        bulletinService.deleteBulletins(ids);
         return ResponseEntity.ok(Message.success("Delete success!"));
     }
 
     @GetMapping("/metrics")
     @Operation(summary = "Query All Bulletin Real Time Metrics Data", 
description = "Query All Bulletin real-time metrics data of monitoring 
indicators")
-    public ResponseEntity<Message<?>> getAllMetricsData(
-            @RequestParam(name = "name") String name,
-            @RequestParam(defaultValue = "0", name = "pageIndex") int 
pageIndex,
-            @RequestParam(defaultValue = "10", name = "pageSize") int 
pageSize) {
+    public ResponseEntity<Message<?>> getAllMetricsData(@RequestParam(name = 
"id") Long id) {
         if (!realTimeDataReader.isServerAvailable()) {
             return ResponseEntity.ok(Message.fail(FAIL_CODE, "real time store 
not available"));
         }
-
-        Bulletin bulletin = bulletinService.getBulletinByName(name);
-
-        BulletinMetricsData.BulletinMetricsDataBuilder contentBuilder = 
BulletinMetricsData.builder()
-                .name(bulletin.getName());
-        BulletinMetricsData data = 
bulletinService.buildBulletinMetricsData(contentBuilder, bulletin);
+        BulletinMetricsData data = 
bulletinService.buildBulletinMetricsData(id);
         return ResponseEntity.ok(Message.success(data));
     }
 
diff --git 
a/manager/src/main/java/org/apache/hertzbeat/manager/dao/BulletinDao.java 
b/manager/src/main/java/org/apache/hertzbeat/manager/dao/BulletinDao.java
index c16f55edd..7ad548694 100644
--- a/manager/src/main/java/org/apache/hertzbeat/manager/dao/BulletinDao.java
+++ b/manager/src/main/java/org/apache/hertzbeat/manager/dao/BulletinDao.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.manager.dao;
 
 
 import java.util.List;
-import org.apache.hertzbeat.common.entity.manager.bulletin.Bulletin;
+import org.apache.hertzbeat.common.entity.manager.Bulletin;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
diff --git 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinMetricsData.java
 
b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/BulletinMetricsData.java
similarity index 98%
rename from 
common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinMetricsData.java
rename to 
manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/BulletinMetricsData.java
index 33f93a200..0a288cd27 100644
--- 
a/common/src/main/java/org/apache/hertzbeat/common/entity/manager/bulletin/BulletinMetricsData.java
+++ 
b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/BulletinMetricsData.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.common.entity.manager.bulletin;
+package org.apache.hertzbeat.manager.pojo.dto;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.List;
diff --git 
a/manager/src/main/java/org/apache/hertzbeat/manager/service/BulletinService.java
 
b/manager/src/main/java/org/apache/hertzbeat/manager/service/BulletinService.java
index b7022fb29..f69840e6f 100644
--- 
a/manager/src/main/java/org/apache/hertzbeat/manager/service/BulletinService.java
+++ 
b/manager/src/main/java/org/apache/hertzbeat/manager/service/BulletinService.java
@@ -19,13 +19,9 @@ package org.apache.hertzbeat.manager.service;
 
 import java.util.List;
 import java.util.Optional;
-import org.apache.hertzbeat.common.entity.manager.bulletin.Bulletin;
-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.manager.Bulletin;
+import org.apache.hertzbeat.manager.pojo.dto.BulletinMetricsData;
 import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.jpa.domain.Specification;
 
 /**
  * Bulletin Service
@@ -35,50 +31,40 @@ public interface BulletinService {
     /**
      * validate Bulletin
      */
-    void validate(BulletinDto bulletindto) throws IllegalArgumentException;
-
-    /**
-     * Get Bulletin by name
-     */
-    Bulletin getBulletinByName(String name);
-
+    void validate(Bulletin bulletin) throws IllegalArgumentException;
+    
     /**
      * Get Bulletin by id
      */
     Optional<Bulletin> getBulletinById(Long id);
 
-    /**
-     * Get all names
-     */
-    List<String> getAllNames();
-
-
-    /**
-     * delete Bulletin by id
-     */
-    void deleteBulletinByName(List<String> names);
-
-
     /**
      * Save Bulletin
      */
-    void editBulletin(BulletinDto bulletinDto);
+    void editBulletin(Bulletin bulletin);
 
     /**
      * Add Bulletin
      */
-    void addBulletin(BulletinDto bulletinDto);
+    void addBulletin(Bulletin bulletin);
+    
+    /**
+     * deal with the bulletin
+     */
+    BulletinMetricsData buildBulletinMetricsData(Long id);
 
     /**
-     * Dynamic conditional query
-     * @param specification Query conditions
-     * @param pageRequest Paging parameters
-     * @return The query results
+     * query bulletins
+     * @param search search name
+     * @param pageIndex page index
+     * @param pageSize page size
+     * @return bulletins
      */
-    Page<BulletinVo> getBulletins(Specification<Bulletin> specification, 
PageRequest pageRequest);
+    Page<Bulletin> getBulletins(String search, Integer pageIndex, Integer 
pageSize);
 
     /**
-     * deal with the bulletin
+     * delete bulletins
+     * @param ids bulletin ids
      */
-    BulletinMetricsData 
buildBulletinMetricsData(BulletinMetricsData.BulletinMetricsDataBuilder 
contentBuilder, Bulletin bulletin);
+    void deleteBulletins(List<Long> ids);
 }
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 9738bd4fd..a12fbb5ae 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
@@ -17,30 +17,24 @@
 
 package org.apache.hertzbeat.manager.service.impl;
 
-import com.fasterxml.jackson.core.type.TypeReference;
+import jakarta.persistence.criteria.Predicate;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.TreeMap;
-import java.util.stream.Collectors;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.hertzbeat.common.entity.manager.Monitor;
-import org.apache.hertzbeat.common.entity.manager.bulletin.Bulletin;
-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.manager.Bulletin;
+import org.apache.hertzbeat.manager.pojo.dto.BulletinMetricsData;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
-import org.apache.hertzbeat.common.util.JsonUtil;
-import org.apache.hertzbeat.common.util.SnowFlakeIdGenerator;
 import org.apache.hertzbeat.manager.dao.BulletinDao;
 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;
-import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
@@ -49,9 +43,9 @@ import 
org.springframework.transaction.annotation.Transactional;
 /**
  * Bulletin Service Implementation
  */
-
 @Service
 @Slf4j
+@Transactional(rollbackFor = Exception.class)
 public class BulletinServiceImpl implements BulletinService {
 
     private static final String NO_DATA = "No Data";
@@ -67,58 +61,39 @@ public class BulletinServiceImpl implements BulletinService 
{
     @Autowired
     private RealTimeDataReader realTimeDataReader;
 
-
     /**
      * validate Bulletin
      */
     @Override
-    public void validate(BulletinDto bulletinDto) throws 
IllegalArgumentException {
-        if (bulletinDto == null) {
+    public void validate(Bulletin bulletin) throws IllegalArgumentException {
+        if (bulletin == null) {
             throw new IllegalArgumentException("Bulletin cannot be null");
         }
-        if (bulletinDto.getApp() == null || bulletinDto.getApp().isEmpty()) {
+        if (bulletin.getApp() == null || bulletin.getApp().isEmpty()) {
             throw new IllegalArgumentException("Bulletin app cannot be null or 
empty");
         }
-        if (bulletinDto.getFields() == null || 
bulletinDto.getFields().isEmpty()) {
+        if (bulletin.getFields() == null || bulletin.getFields().isEmpty()) {
             throw new IllegalArgumentException("Bulletin fields cannot be null 
or empty");
         }
-        if (bulletinDto.getMonitorIds() == null || 
bulletinDto.getMonitorIds().isEmpty()) {
+        if (bulletin.getMonitorIds() == null || 
bulletin.getMonitorIds().isEmpty()) {
             throw new IllegalArgumentException("Bulletin monitorIds cannot be 
null or empty");
         }
-        if (bulletinDao.countByName(bulletinDto.getName()) > 0) {
+        if (bulletinDao.countByName(bulletin.getName()) > 0) {
             throw new IllegalArgumentException("Bulletin name duplicated");
         }
     }
 
-
-    /**
-     * Pageable query Bulletin
-     */
-    @Override
-    public Bulletin getBulletinByName(String name) {
-        return bulletinDao.findByName(name);
-    }
-
-    /**
-     * Get all names
-     */
-    @Override
-    public List<String> getAllNames() {
-        return 
bulletinDao.findAll().stream().map(Bulletin::getName).distinct().toList();
-    }
-
-
     /**
      * Save Bulletin
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void editBulletin(BulletinDto bulletinDto) {
-        try {
-            //TODO: update bulletin
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+    public void editBulletin(Bulletin bulletin) {
+        Optional<Bulletin> optional = bulletinDao.findById(bulletin.getId());
+        if (optional.isEmpty()) {
+            throw new IllegalArgumentException("Bulletin not found");
         }
+        bulletinDao.save(bulletin);
     }
 
     /**
@@ -126,58 +101,22 @@ public class BulletinServiceImpl implements 
BulletinService {
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void addBulletin(BulletinDto bulletinDto) {
-        try {
-            Bulletin bulletin = new Bulletin();
-            bulletin.setName(bulletinDto.getName());
-            bulletin.setId(SnowFlakeIdGenerator.generateId());
-            Map<String, List<String>> map = bulletinDto.getFields();
-            Map<String, List<String>> sortedMap = new TreeMap<>(map);
-            String fields = JsonUtil.toJson(sortedMap);
-            bulletin.setFields(fields);
-            bulletin.setMonitorIds(bulletinDto.getMonitorIds());
-            bulletin.setApp(bulletinDto.getApp());
-            bulletinDao.save(bulletin);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Dynamic conditional query
-     *
-     * @param specification Query conditions
-     * @param pageRequest   Paging parameters
-     * @return The query results
-     */
-    @Override
-    public Page<BulletinVo> getBulletins(Specification<Bulletin> 
specification, PageRequest pageRequest) {
-        List<BulletinVo> voList = new ArrayList<>();
-        Page<Bulletin> bulletinPage = Page.empty(pageRequest);
-        try {
-            bulletinPage = bulletinDao.findAll(specification, pageRequest);
-            voList = bulletinPage.stream().map(bulletin -> {
-                BulletinVo vo = new BulletinVo();
-                vo.setId(bulletin.getId());
-                vo.setName(bulletin.getName());
-                vo.setTags(bulletin.getTags());
-                vo.setMonitorId(bulletin.getMonitorIds());
-                vo.setApp(bulletin.getApp());
-                return vo;
-            }).collect(Collectors.toList());
-        } catch (Exception e) {
-            log.error("Failed to query bulletin: {}", e.getLocalizedMessage(), 
e);
-        }
-        long total = bulletinPage.getTotalElements();
-        return new PageImpl<>(voList, pageRequest, total);
+    public void addBulletin(Bulletin bulletin) {
+        bulletinDao.save(bulletin);
     }
 
     /**
      * deal with the bulletin
-     *
      */
     @Override
-    public BulletinMetricsData 
buildBulletinMetricsData(BulletinMetricsData.BulletinMetricsDataBuilder 
contentBuilder, Bulletin bulletin) {
+    public BulletinMetricsData buildBulletinMetricsData(Long id) {
+        Optional<Bulletin> optional = bulletinDao.findById(id);
+        if (optional.isEmpty()) {
+            throw new IllegalArgumentException("Bulletin not found");
+        }
+        Bulletin bulletin = optional.get();
+        BulletinMetricsData.BulletinMetricsDataBuilder contentBuilder = 
BulletinMetricsData.builder()
+                .name(bulletin.getName());
         List<BulletinMetricsData.Data> dataList = new ArrayList<>();
         for (Long monitorId : bulletin.getMonitorIds()) {
             Monitor monitor = monitorService.getMonitor(monitorId);
@@ -187,7 +126,7 @@ public class BulletinServiceImpl implements BulletinService 
{
                     .host(monitor.getHost());
 
             List<BulletinMetricsData.Metric> metrics = new ArrayList<>();
-            Map<String, List<String>> fieldMap = 
JsonUtil.fromJson(bulletin.getFields(), new TypeReference<>() {});
+            Map<String, List<String>> fieldMap = bulletin.getFields();
 
             if (fieldMap != null) {
                 for (Map.Entry<String, List<String>> entry : 
fieldMap.entrySet()) {
@@ -235,27 +174,32 @@ public class BulletinServiceImpl implements 
BulletinService {
         return contentBuilder.build();
     }
 
+    @Override
+    public Page<Bulletin> getBulletins(String search, Integer pageIndex, 
Integer pageSize) {
+        pageIndex = pageIndex == null ? 0 : pageIndex;
+        pageSize = pageSize == null ? Integer.MAX_VALUE : pageSize;
+        Specification<Bulletin> specification = (root, query, criteriaBuilder) 
-> {
+            Predicate predicate = criteriaBuilder.conjunction();
+            if (StringUtils.isNotBlank(search)) {
+                Predicate predicateName = 
criteriaBuilder.like(root.get("name"), "%" + search + "%");
+                predicate = criteriaBuilder.and(predicateName);
+            }
+            return predicate;
+        };
+        PageRequest pageRequest = PageRequest.of(pageIndex, pageSize);
+        return bulletinDao.findAll(specification, pageRequest);
+    }
 
+    @Override
+    public void deleteBulletins(List<Long> ids) {
+        bulletinDao.deleteAllById(ids);
+    }
+    
     /**
      * Get Bulletin by id
-     *
      */
     @Override
     public Optional<Bulletin> getBulletinById(Long id) {
         return bulletinDao.findById(id);
     }
-
-    /**
-     * delete Bulletin by names
-     *
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void deleteBulletinByName(List<String> names) {
-        try {
-            bulletinDao.deleteByNameIn(names);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
 }
diff --git 
a/manager/src/test/java/org/apache/hertzbeat/manager/controller/BulletinControllerTest.java
 
b/manager/src/test/java/org/apache/hertzbeat/manager/controller/BulletinControllerTest.java
index 2001dcfc0..cc383f722 100644
--- 
a/manager/src/test/java/org/apache/hertzbeat/manager/controller/BulletinControllerTest.java
+++ 
b/manager/src/test/java/org/apache/hertzbeat/manager/controller/BulletinControllerTest.java
@@ -22,13 +22,9 @@ import static org.mockito.Mockito.doAnswer;
 import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
 import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.hertzbeat.common.constants.CommonConstants;
-import org.apache.hertzbeat.common.entity.manager.bulletin.Bulletin;
-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;
+import org.apache.hertzbeat.manager.pojo.dto.BulletinMetricsData;
 import org.apache.hertzbeat.manager.service.BulletinService;
 import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataReader;
 import org.junit.jupiter.api.BeforeEach;
@@ -63,7 +59,7 @@ class BulletinControllerTest {
 
     @Test
     void testAddNewBulletin() throws Exception {
-        BulletinDto bulletinDto = new BulletinDto();
+        Bulletin bulletinDto = new Bulletin();
         doAnswer(invocation -> {
             throw new IllegalArgumentException("Invalid bulletin");
         }).when(bulletinService).validate(bulletinDto);
@@ -89,7 +85,7 @@ class BulletinControllerTest {
 
     @Test
     void testEditBulletin() throws Exception {
-        BulletinDto bulletinDto = new BulletinDto();
+        Bulletin bulletinDto = new Bulletin();
         doAnswer(invocation -> {
             throw new IllegalArgumentException("Invalid bulletin");
         }).when(bulletinService).validate(bulletinDto);
@@ -113,71 +109,20 @@ class BulletinControllerTest {
                 .andExpect(jsonPath("$.code").value((int) 
CommonConstants.SUCCESS_CODE));
     }
 
-    @Test
-    void testGetBulletinByName() throws Exception {
-        
Mockito.when(bulletinService.getBulletinByName(any(String.class))).thenReturn(null);
-        
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/bulletin/{name}", "test"))
-                .andExpect(status().isOk())
-                .andExpect(jsonPath("$.code").value((int) 
CommonConstants.SUCCESS_CODE));
-
-        
Mockito.when(bulletinService.getBulletinByName(any(String.class))).thenThrow(new
 RuntimeException("test"));
-        
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/bulletin/{name}", "test"))
-                .andExpect(status().isOk())
-                .andExpect(jsonPath("$.code").value((int) 
CommonConstants.FAIL_CODE));
-    }
-
-    @Test
-    void testGetAllNames() throws Exception {
-        List<String> names = new ArrayList<String>();
-        names.add("one");
-        names.add("two");
-        Mockito.when(bulletinService.getAllNames()).thenReturn(names);
-        this.mockMvc.perform(MockMvcRequestBuilders.get("/api/bulletin/names"))
-                .andExpect(status().isOk())
-                .andExpect(jsonPath("$.data[0]").value("one"))
-                .andExpect(jsonPath("$.code").value((int) 
CommonConstants.SUCCESS_CODE));
-    }
-
-    @Test
-    void testDeleteBulletinByName() throws Exception {
-        
Mockito.doNothing().when(bulletinService).deleteBulletinByName(any(List.class));
-        this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/bulletin")
-                .param("names", "one"))
-                .andExpect(status().isOk())
-                .andExpect(jsonPath("$.code").value((int) 
CommonConstants.SUCCESS_CODE));
-
-        // will throw exception
-        Mockito.doThrow(new 
RuntimeException("test")).when(bulletinService).deleteBulletinByName(any(List.class));
-        this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/bulletin")
-                .param("names", "one"))
-                .andExpect(status().isOk())
-                .andExpect(jsonPath("$.code").value((int) 
CommonConstants.FAIL_CODE));
-    }
-
     @Test
     void testGetAllMetricsData() throws Exception {
         // server is not available
         Mockito.when(realTimeDataReader.isServerAvailable()).thenReturn(false);
-        
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/bulletin/metrics")
-                .param("name", "test")
-                .param("pageIndex", "0")
-                .param("pageSize", "10"))
+        
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/bulletin/metrics?id=33"))
                 .andExpect(status().isOk())
                 .andExpect(jsonPath("$.code").value((int) 
CommonConstants.FAIL_CODE));
-
-        // normal
-        Bulletin bulletin = new Bulletin();
+        
         BulletinMetricsData data = new BulletinMetricsData();
         data.setName("sample");
         Mockito.when(realTimeDataReader.isServerAvailable()).thenReturn(true);
-        Mockito.when(bulletinService.getBulletinByName(any(String.class)))
-                .thenReturn(bulletin);
-        
Mockito.when(bulletinService.buildBulletinMetricsData(any(BulletinMetricsData.BulletinMetricsDataBuilder.class),
 any(Bulletin.class)))
+        Mockito.when(bulletinService.buildBulletinMetricsData(any(Long.class)))
             .thenReturn(data);
-        
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/bulletin/metrics")
-            .param("name", "test")
-            .param("pageIndex", "0")
-            .param("pageSize", "10"))
+        
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/bulletin/metrics?id=33"))
             .andExpect(status().isOk())
             .andExpect(jsonPath("$.data.name").value("sample"))
             .andExpect(jsonPath("$.code").value((int) 
CommonConstants.SUCCESS_CODE));
diff --git 
a/manager/src/test/java/org/apache/hertzbeat/manager/service/BulletinServiceTest.java
 
b/manager/src/test/java/org/apache/hertzbeat/manager/service/BulletinServiceTest.java
index a69175eba..d74629257 100644
--- 
a/manager/src/test/java/org/apache/hertzbeat/manager/service/BulletinServiceTest.java
+++ 
b/manager/src/test/java/org/apache/hertzbeat/manager/service/BulletinServiceTest.java
@@ -22,8 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyList;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
@@ -33,9 +31,8 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.hertzbeat.common.entity.manager.Monitor;
-import org.apache.hertzbeat.common.entity.manager.bulletin.Bulletin;
-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;
+import org.apache.hertzbeat.manager.pojo.dto.BulletinMetricsData;
 import org.apache.hertzbeat.manager.dao.BulletinDao;
 import org.apache.hertzbeat.manager.service.impl.BulletinServiceImpl;
 import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataReader;
@@ -73,11 +70,11 @@ public class BulletinServiceTest {
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
-            bulletinService.validate(new BulletinDto());
+            bulletinService.validate(new Bulletin());
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
-            BulletinDto obj = new BulletinDto();
+            Bulletin obj = new Bulletin();
             obj.setApp("app");
             bulletinService.validate(obj);
         });
@@ -86,7 +83,7 @@ public class BulletinServiceTest {
             Map<String, List<String>> fields = new HashMap<String, 
List<String>>();
             fields.put("field1", null);
 
-            BulletinDto obj = new BulletinDto();
+            Bulletin obj = new Bulletin();
             obj.setApp("app");
             obj.setFields(fields);
             bulletinService.validate(obj);
@@ -99,7 +96,7 @@ public class BulletinServiceTest {
             List<Long> ids = new ArrayList<Long>();
             ids.add((long) 1);
 
-            BulletinDto obj = new BulletinDto();
+            Bulletin obj = new Bulletin();
             obj.setApp("app");
             obj.setFields(fields);
             obj.setMonitorIds(ids);
@@ -107,35 +104,12 @@ public class BulletinServiceTest {
         });
     }
 
-    @Test
-    public void testGetBulletinByName() throws Exception {
-        Bulletin bulletin = new Bulletin();
-
-        when(bulletinDao.findByName("test")).thenReturn(bulletin);
-        assertEquals(bulletin, bulletinService.getBulletinByName("test"));
-    }
-
-    @Test
-    public void testGetAllNames() throws Exception {
-        Bulletin bulletin = new Bulletin();
-        bulletin.setName("test");
-
-        List<Bulletin> items = new ArrayList<Bulletin>();
-        items.add(bulletin);
-
-        List<String> names = new ArrayList<String>();
-        names.add("test");
-
-        when(bulletinDao.findAll()).thenReturn(items);
-        assertEquals(names, bulletinService.getAllNames());
-    }
-
     @Test
     public void testAddBulletin() throws Exception {
         Map<String, List<String>> fields = new HashMap<String, List<String>>();
         fields.put("field1", null);
 
-        BulletinDto bulletinDto = new BulletinDto();
+        Bulletin bulletinDto = new Bulletin();
         bulletinDto.setApp("app");
         bulletinDto.setFields(fields);
 
@@ -157,28 +131,28 @@ public class BulletinServiceTest {
         Page<Bulletin> items = new PageImpl<Bulletin>(content, pageRequest, 
total);
 
         when(bulletinDao.findAll(any(Specification.class), 
any(PageRequest.class))).thenReturn(items);
-        assertNotNull(bulletinService.getBulletins(null, pageRequest));
+        assertNotNull(bulletinService.getBulletins(null, null, null));
     }
 
     @Test
     public void testBuildBulletinMetricsData() throws Exception {
         List<Long> ids = new ArrayList<Long>();
         ids.add((long) 1);
-
         Bulletin bulletin = new Bulletin();
         bulletin.setId((long) 1);
         bulletin.setMonitorIds(ids);
-        bulletin.setFields("""
-            {"1": ["1", "2"]}
-            """);
+        HashMap<String, List<String>> fields = new HashMap<>();
+        fields.put("1", List.of("1", "2"));
+        bulletin.setFields(fields);
 
         BulletinMetricsData.BulletinMetricsDataBuilder contentBuilder = 
BulletinMetricsData.builder();
 
         Monitor monitor = new Monitor();
 
+        
when(bulletinDao.findById(any(Long.class))).thenReturn(java.util.Optional.of(bulletin));
         when(realTimeDataReader.getCurrentMetricsData(any(), 
any(String.class))).thenReturn(null);
         when(monitorService.getMonitor(any(Long.class))).thenReturn(monitor);
-        assertNotNull(bulletinService.buildBulletinMetricsData(contentBuilder, 
bulletin));
+        
assertNotNull(bulletinService.buildBulletinMetricsData(any(Long.class)));
     }
 
     @Test
@@ -189,22 +163,4 @@ public class BulletinServiceTest {
         when(bulletinDao.findById((long) 
1)).thenReturn(java.util.Optional.of(bulletin));
         assertEquals(bulletin, bulletinService.getBulletinById((long) 
1).get());
     }
-
-    @Test
-    public void testDeleteBulletinByName() throws Exception {
-        List<String> names = new ArrayList<String>();
-        names.add("test");
-
-        assertDoesNotThrow(() -> {
-            bulletinService.deleteBulletinByName(names);
-        });
-
-        assertThrows(RuntimeException.class, () -> {
-            doAnswer(invocation -> {
-                throw new RuntimeException("test");
-            }).when(bulletinDao).deleteByNameIn(anyList());
-
-            bulletinService.deleteBulletinByName(null);
-        });
-    }
 }
diff --git a/web-app/src/app/routes/bulletin/bulletin.component.html 
b/web-app/src/app/routes/bulletin/bulletin.component.html
index f8f8eb0ba..795d16b58 100644
--- a/web-app/src/app/routes/bulletin/bulletin.component.html
+++ b/web-app/src/app/routes/bulletin/bulletin.component.html
@@ -28,10 +28,6 @@
 
 <app-toolbar>
   <ng-template #left>
-    <button nz-button nz-dropdown [nzDropdownMenu]="time_menu" 
nzPlacement="bottomLeft">
-      <span *ngIf="deadline > 0"> {{ 'monitors.detail.auto-refresh' | i18n : { 
time: countDownTime } }} </span>
-      <span *ngIf="deadline <= 0"> {{ 'monitors.detail.close-refresh' | i18n 
}} </span>
-    </button>
     <button nz-button nzType="primary" (click)="sync()" nz-tooltip 
[nzTooltipTitle]="'common.refresh' | i18n">
       <i nz-icon nzType="sync" nzTheme="outline"></i>
     </button>
@@ -44,14 +40,20 @@
       <i nz-icon nzType="edit" nzTheme="outline"></i>
       {{ 'bulletin.edit' | i18n }}
     </button>-->
-    <button *ngIf="currentDefine" nz-button nzType="primary" nzDanger 
(click)="onDeleteBulletinDefines()">
+    <button *ngIf="currentBulletin" nz-button nzType="primary" nzDanger 
(click)="onDeleteBulletinDefines()">
       <i nz-icon nzType="delete" nzTheme="outline"></i>
       {{ 'bulletin.delete' | i18n }}
     </button>
-    <button *ngIf="currentDefine" nz-button nzType="primary" nzDanger 
(click)="onBatchDeleteBulletinDefines()">
+    <button *ngIf="currentBulletin" nz-button nzType="primary" nzDanger 
(click)="onBatchDeleteBulletinDefines()">
       <i nz-icon nzType="delete" nzTheme="outline"></i>
       {{ 'bulletin.batch.delete' | i18n }}
     </button>
+  </ng-template>
+  <ng-template #right>
+    <button nz-button nz-dropdown [nzDropdownMenu]="time_menu" 
nzPlacement="bottomLeft">
+      <span *ngIf="deadline > 0"> {{ 'monitors.detail.auto-refresh' | i18n : { 
time: countDownTime } }} </span>
+      <span *ngIf="deadline <= 0"> {{ 'monitors.detail.close-refresh' | i18n 
}} </span>
+    </button>
     <nz-dropdown-menu #time_menu="nzDropdownMenu">
       <ul nz-menu>
         <li nz-menu-item (click)="configRefreshDeadline(10)"> {{ 
'monitors.detail.config-refresh' | i18n : { time: 10 } }} </li>
@@ -65,7 +67,7 @@
 </app-toolbar>
 
 <nz-tabset nzType="card" (nzSelectedIndexChange)="onTabChange($event)">
-  <nz-tab *ngFor="let tab of tabs" [nzTitle]="tab">
+  <nz-tab *ngFor="let tab of bulletins" [nzTitle]="tab.name">
     <ng-container *ngIf="metricsData">
       <nz-table
         #fixedTable
@@ -231,7 +233,7 @@
   (nzOnCancel)="onBatchDeleteModalCancel()"
   (nzOnOk)="onBatchDeleteModalOk()"
   nzMaskClosable="false"
-  nzWidth="70%"
+  nzWidth="40%"
 >
   <div *nzModalContent class="-inner-content">
     <form nz-form #defineForm="ngForm">
@@ -241,11 +243,11 @@
           <nz-select
             nzMode="multiple"
             nzPlaceHolder="Please select"
-            [(ngModel)]="this.deleteBulletinNames"
+            [(ngModel)]="this.deleteBulletinIds"
             [nzShowSearch]="true"
             name="delete"
           >
-            <nz-option *ngFor="let tab of tabs" [nzLabel]="tab" 
[nzValue]="tab"></nz-option>
+            <nz-option *ngFor="let tab of bulletins" [nzLabel]="tab.name" 
[nzValue]="tab.id"></nz-option>
           </nz-select>
         </nz-form-control>
       </nz-form-item>
diff --git a/web-app/src/app/routes/bulletin/bulletin.component.ts 
b/web-app/src/app/routes/bulletin/bulletin.component.ts
index bc1578e50..dd6b9b1f2 100644
--- a/web-app/src/app/routes/bulletin/bulletin.component.ts
+++ b/web-app/src/app/routes/bulletin/bulletin.component.ts
@@ -50,11 +50,12 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
     @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
   ) {}
   search!: string;
-  tabs!: string[];
+  bulletins!: BulletinDefine[];
+  currentTab: number = 0;
+  currentBulletin!: BulletinDefine;
   metricsData!: any;
   tableLoading: boolean = true;
-  bulletinName!: string;
-  deleteBulletinNames: string[] = [];
+  deleteBulletinIds: number[] = [];
   isAppListLoading = false;
   isMonitorListLoading = false;
   treeNodes!: NzTreeNodeOptions[];
@@ -69,7 +70,6 @@ export class BulletinComponent implements OnInit, OnDestroy {
   pageIndex: number = 1;
   pageSize: number = 8;
   total: number = 0;
-  currentTab: number = 0;
   refreshInterval: any;
   deadline = 30;
   countDownTime: number = 0;
@@ -88,7 +88,7 @@ export class BulletinComponent implements OnInit, OnDestroy {
   }
 
   sync() {
-    this.loadData(this.pageIndex - 1, this.pageSize);
+    this.loadCurrentBulletinData();
   }
 
   configRefreshDeadline(deadlineTime: number) {
@@ -102,7 +102,7 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
       this.countDownTime = Math.max(0, this.countDownTime - 1);
       this.cdr.detectChanges();
       if (this.countDownTime == 0) {
-        this.loadTabs();
+        this.loadCurrentBulletinData();
         this.countDownTime = this.deadline;
         this.cdr.detectChanges();
       }
@@ -117,8 +117,8 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
   }
 
   onEditBulletinDefine() {
-    if (this.currentDefine) {
-      this.define = this.currentDefine;
+    if (this.currentBulletin) {
+      this.define = this.currentBulletin;
       this.onAppChange(this.define.app);
       // this.tempMetrics.add(...this.define.fields.keys());
       this.isManageModalAdd = false;
@@ -127,12 +127,12 @@ export class BulletinComponent implements OnInit, 
OnDestroy {
     }
   }
 
-  deleteBulletinDefines(defineNames: string[]) {
-    if (defineNames == null || defineNames.length == 0) {
+  deleteBulletinDefines(defineIds: number[]) {
+    if (defineIds == null || defineIds.length == 0) {
       
this.notifySvc.warning(this.i18nSvc.fanyi('common.notify.no-select-delete'), 
'');
       return;
     }
-    const deleteDefines$ = 
this.bulletinDefineSvc.deleteBulletinDefines(defineNames).subscribe(
+    const deleteDefines$ = 
this.bulletinDefineSvc.deleteBulletinDefines(defineIds).subscribe(
       message => {
         deleteDefines$.unsubscribe();
         if (message.code === 0) {
@@ -153,7 +153,6 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
   isManageModalOkLoading = false;
   isManageModalAdd = true;
   define: BulletinDefine = new BulletinDefine();
-  currentDefine!: BulletinDefine | null;
 
   onManageModalCancel() {
     this.isManageModalVisible = false;
@@ -173,8 +172,6 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
   onManageModalOk() {
     this.isManageModalOkLoading = true;
     this.define.fields = this.fields;
-    // clear fields
-    this.fields = {};
     if (this.isManageModalAdd) {
       const modalOk$ = this.bulletinDefineSvc
         .newBulletinDefine(this.define)
@@ -189,6 +186,8 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
             if (message.code === 0) {
               
this.notifySvc.success(this.i18nSvc.fanyi('common.notify.new-success'), '');
               this.isManageModalVisible = false;
+              // clear fields
+              this.fields = {};
               this.resetManageModalData();
               this.loadTabs();
             } else {
@@ -213,7 +212,7 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
             if (message.code === 0) {
               this.isManageModalVisible = false;
               
this.notifySvc.success(this.i18nSvc.fanyi('common.notify.edit-success'), '');
-              this.loadData(this.pageIndex - 1, this.pageSize);
+              this.loadTabs();
             } else {
               
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), 
message.msg);
             }
@@ -414,15 +413,21 @@ export class BulletinComponent implements OnInit, 
OnDestroy {
   }
 
   loadTabs() {
-    const allNames$ = this.bulletinDefineSvc.getAllNames().subscribe(
+    const allNames$ = this.bulletinDefineSvc.queryBulletins().subscribe(
       message => {
         allNames$.unsubscribe();
         if (message.code === 0) {
-          this.tabs = message.data;
-          if (this.tabs != null) {
-            this.bulletinName = this.tabs[this.currentTab];
+          let page = message.data;
+          this.bulletins = page.content;
+          this.pageIndex = page.number + 1;
+          this.total = page.totalElements;
+          if (this.bulletins != null) {
+            if (this.currentTab >= this.bulletins.length) {
+              this.currentTab = 0;
+            }
+            this.currentBulletin = this.bulletins[this.currentTab];
+            this.loadCurrentBulletinData();
           }
-          this.loadData(this.pageIndex - 1, this.pageSize);
         } else {
           this.notifySvc.error(this.i18nSvc.fanyi('common.notify.get-fail'), 
message.msg);
         }
@@ -434,51 +439,34 @@ export class BulletinComponent implements OnInit, 
OnDestroy {
     );
   }
 
-  loadData(page: number, size: number) {
+  loadCurrentBulletinData() {
     this.tableLoading = true;
     this.metricsData = [];
-    this.currentDefine = null;
     this.metrics = new Set<string>();
-    if (this.bulletinName != null) {
-      const defineData$ = 
this.bulletinDefineSvc.getBulletinDefine(this.bulletinName).subscribe(
-        message => {
-          if (message.code === 0) {
-            this.currentDefine = message.data;
-
-            const metricData$ = 
this.bulletinDefineSvc.getMonitorMetricsData(this.bulletinName, page, 
size).subscribe(
-              message => {
-                metricData$.unsubscribe();
-                if (message.code === 0 && message.data) {
-                  (this.metricsData = message.data.content).forEach((item: 
any) => {
-                    item.metrics.forEach((metric: any) => {
-                      this.metrics.add(metric.name);
-                    });
-                  });
-                } else if (message.code !== 0) {
-                  this.notifySvc.warning(`${message.msg}`, '');
-                  console.info(`${message.msg}`);
-                }
-                this.tableLoading = false;
-              },
-              error => {
-                console.error(error.msg);
-                metricData$.unsubscribe();
-                this.tableLoading = false;
-              }
-            );
-          } else {
-            this.notifySvc.warning(`${message.msg}`, '');
-            console.info(`${message.msg}`);
-          }
-        },
-        error => {
-          console.error(error.msg);
-          defineData$.unsubscribe();
-          this.tableLoading = false;
-        }
-      );
+    if (this.currentBulletin == null || this.currentBulletin.id == null) {
+      return;
     }
-    this.tableLoading = false;
+    const metricData$ = 
this.bulletinDefineSvc.getMonitorMetricsData(this.currentBulletin?.id).subscribe(
+      message => {
+        metricData$.unsubscribe();
+        if (message.code === 0 && message.data) {
+          (this.metricsData = message.data.content).forEach((item: any) => {
+            item.metrics.forEach((metric: any) => {
+              this.metrics.add(metric.name);
+            });
+          });
+        } else if (message.code !== 0) {
+          this.notifySvc.warning(`${message.msg}`, '');
+          console.info(`${message.msg}`);
+        }
+        this.tableLoading = false;
+      },
+      error => {
+        console.error(error.msg);
+        metricData$.unsubscribe();
+        this.tableLoading = false;
+      }
+    );
   }
 
   getKeys(metricName: string): string[] {
@@ -503,7 +491,7 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
     if (pageIndex !== this.pageIndex || pageSize !== this.pageSize) {
       this.pageIndex = pageIndex;
       this.pageSize = pageSize;
-      this.loadData(pageIndex - 1, pageSize);
+      this.loadTabs();
     }
   }
 
@@ -518,7 +506,7 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
       nzOkDanger: true,
       nzOkType: 'primary',
       nzClosable: false,
-      nzOnOk: () => this.deleteBulletinDefines([this.bulletinName])
+      nzOnOk: () => this.deleteBulletinDefines([this.currentBulletin.id])
     });
   }
 
@@ -531,7 +519,7 @@ export class BulletinComponent implements OnInit, OnDestroy 
{
   }
 
   onBatchDeleteModalOk() {
-    this.deleteBulletinDefines(this.deleteBulletinNames);
+    this.deleteBulletinDefines(this.deleteBulletinIds);
     this.isBatchDeleteModalOkLoading = false;
     this.isBatchDeleteModalVisible = false;
   }
@@ -540,10 +528,9 @@ export class BulletinComponent implements OnInit, 
OnDestroy {
 
   onTabChange($event: number) {
     this.currentTab = $event;
-    this.bulletinName = this.tabs[this.currentTab];
+    this.currentBulletin = this.bulletins[this.currentTab];
     this.metricsData = [];
-    this.loadData(this.pageIndex - 1, this.pageSize);
-    console.log(this.metricsData);
+    this.loadTabs();
     this.countDownTime = this.deadline;
     this.cdr.detectChanges();
   }
diff --git a/web-app/src/app/service/bulletin-define.service.ts 
b/web-app/src/app/service/bulletin-define.service.ts
index cd92c4c53..2d57746c0 100644
--- a/web-app/src/app/service/bulletin-define.service.ts
+++ b/web-app/src/app/service/bulletin-define.service.ts
@@ -42,46 +42,24 @@ export class BulletinDefineService {
     return this.http.put<Message<any>>(bulletin_define_uri, body);
   }
 
-  public getBulletinDefine(name: string) {
-    return this.http.get<Message<any>>(`${bulletin_define_uri}/${name}`);
-  }
-
-  public deleteBulletinDefines(names: string[]): Observable<Message<any>> {
+  public deleteBulletinDefines(ids: number[]): Observable<Message<any>> {
     let params = new HttpParams();
-    names.forEach(name => {
-      params = params.append('names', name);
+    ids.forEach(name => {
+      params = params.append('ids', name);
     });
-
     return this.http.delete<Message<any>>(bulletin_define_uri, { params });
   }
 
-  public getMonitorMetricsData(
-    name: string,
-    pageIndex: number,
-    pageSize: number,
-    sortField?: string | null,
-    sortOrder?: string | null
-  ): Observable<Message<Page<Monitor>>> {
-    pageIndex = pageIndex ? pageIndex : 0;
-    pageSize = pageSize ? pageSize : 8;
-    // 注意HttpParams是不可变对象 需要保存set后返回的对象为最新对象
+  public getMonitorMetricsData(id: number): Observable<Message<Page<Monitor>>> 
{
     let httpParams = new HttpParams();
     httpParams = httpParams.appendAll({
-      name: name,
-      pageIndex: pageIndex,
-      pageSize: pageSize
+      id: id
     });
-    if (sortField != null && sortOrder != null) {
-      httpParams = httpParams.appendAll({
-        sort: sortField,
-        order: sortOrder == 'ascend' ? 'asc' : 'desc'
-      });
-    }
     const options = { params: httpParams };
     return this.http.get<Message<any>>(`${bulletin_define_uri}/metrics`, 
options);
   }
 
-  public getAllNames(): Observable<Message<string[]>> {
-    return this.http.get<Message<string[]>>(`${bulletin_define_uri}/names`);
+  public queryBulletins(): Observable<Message<any>> {
+    return this.http.get<Message<string[]>>(`${bulletin_define_uri}`);
   }
 }
diff --git a/web-app/src/assets/i18n/en-US.json 
b/web-app/src/assets/i18n/en-US.json
index 15f972f0e..d5c4d448e 100644
--- a/web-app/src/assets/i18n/en-US.json
+++ b/web-app/src/assets/i18n/en-US.json
@@ -44,20 +44,6 @@
       "silence": "Alarm Silence",
       "dispatch": "Notification"
     },
-    "bulletin": {
-      "new": "Add New Bulletin Item",
-      "edit": "Edit Bulletin Item",
-      "delete": "Delete Bulletin Item",
-      "batch.delete": "Batch delete Bulletin Items",
-      "name": "Bulletin Name",
-      "name.placeholder": "Please enter a custom bulletin name",
-      "monitor.type": "Monitor Type",
-      "monitor.name": "Monitor Task Name",
-      "monitor.metrics": "Monitor Metrics",
-      "help.message.content": "Custom Monitoring Bulletin",
-      "help.content": "Custom monitoring bulletin, displaying selected metrics 
of a specific monitor in table form",
-      "help.link": "https://hertzbeat.apache.org/docs/help/bulletin";
-    },
     "advanced": {
       "": "Advanced",
       "collector": "Collector Cluster",
@@ -152,10 +138,10 @@
     }
   },
   "bulletin": {
-    "new": "Add New Bulletin Item",
-    "edit": "Edit Bulletin Item",
-    "delete": "Delete Bulletin Item",
-    "batch.delete": "Batch delete Bulletin Item",
+    "new": "New Bulletin",
+    "edit": "Edit Bulletin",
+    "delete": "Delete Bulletin",
+    "batch.delete": "Batch Delete Bulletin",
     "name": "Bulletin Name",
     "name.placeholder": "Please enter a custom bulletin name",
     "monitor.type": "Monitor Type",


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

Reply via email to