Compare commits

..
Author SHA1 Message Date
Logic 047d59381c Merge branch 'master' into theme-dark-update
Signed-off-by: Logic <zqr10159@dromara.org>
2025-02-07 19:20:37 +08:00
Logic cdb4219065 style(alert-center): enhance 3D transformation and z-index layers
- Add transform-style and perspective to alert-center container
- Implement relative positioning and z-index layering for alert cards
- Adjust z-index values for expanded and hovered cards
- Update alert-details and collapse components with relative positioning
- Remove redundant perspective property from alert-cards
2025-02-07 19:18:17 +08:00
yunfan24andtomsun28 5e69f4dfd0 [bugfix] Fix the issue where the monitoring status is not updated. (#3056)
Co-authored-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 16:12:47 +08:00
tomsun28 aeb0083394 [improve] update theme ui color (#3057)
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 15:47:19 +08:00
tomsun28 cabe8d8ff9 Merge branch 'master' into theme-dark-update 2025-02-07 10:43:58 +08:00
Logic 02f635bdd3 [improve](alert-center) enhance alert card animations and interactions (#3055) 2025-02-07 10:18:52 +08:00
tomsun28 4ac8170d21 [webapp] bugfix edit monitor http query params error
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 00:44:07 +08:00
tomsun28 5641a5ca89 [webapp] bugfix edit monitor http query params error
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 00:38:18 +08:00
tomsun28 de8bd79ef9 [alert] update theme ui color
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-07 00:19:36 +08:00
tomsun28 30332969ee [alert] add multi query expr threshold unit test
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-02-06 23:41:15 +08:00
15 changed files with 128 additions and 130 deletions
@@ -18,8 +18,11 @@
package org.apache.hertzbeat.warehouse.store;
import java.util.Optional;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.entity.manager.Monitor;
import org.apache.hertzbeat.common.entity.message.CollectRep;
import org.apache.hertzbeat.common.queue.CommonDataQueue;
import org.apache.hertzbeat.plugin.PostCollectPlugin;
@@ -27,7 +30,6 @@ import org.apache.hertzbeat.plugin.runner.PluginRunner;
import org.apache.hertzbeat.warehouse.WarehouseWorkerPool;
import org.apache.hertzbeat.warehouse.store.history.HistoryDataWriter;
import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataWriter;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@@ -44,6 +46,8 @@ public class DataStorageDispatch {
private final RealTimeDataWriter realTimeDataWriter;
private final Optional<HistoryDataWriter> historyDataWriter;
private final PluginRunner pluginRunner;
@PersistenceContext
private EntityManager entityManager;
public DataStorageDispatch(CommonDataQueue commonDataQueue,
WarehouseWorkerPool workerPool,
@@ -87,24 +91,16 @@ public class DataStorageDispatch {
if (metricsData.getPriority() == 0) {
long id = metricsData.getId();
CollectRep.Code code = metricsData.getCode();
// query current status
String queryStatusSql = "SELECT status FROM hzb_monitor WHERE id = ?";
try {
int currentStatus = jdbcTemplate.queryForObject(queryStatusSql, Integer.class, id);
if (code == CollectRep.Code.SUCCESS && currentStatus == CommonConstants.MONITOR_DOWN_CODE) {
// if collect success and current status is DOWN, update to UP
String sql = "UPDATE hzb_monitor SET status = ? WHERE id = ?";
jdbcTemplate.update(sql, CommonConstants.MONITOR_UP_CODE, id);
} else if (code != CollectRep.Code.SUCCESS && currentStatus == CommonConstants.MONITOR_UP_CODE) {
// if collect failed and current status is UP, update to DOWN
String sql = "UPDATE hzb_monitor SET status = ? WHERE id = ?";
jdbcTemplate.update(sql, CommonConstants.MONITOR_DOWN_CODE, id);
String sql = "UPDATE hzb_monitor SET status = ? WHERE id = ? AND status != ?";
int status = code == CollectRep.Code.SUCCESS ? CommonConstants.MONITOR_UP_CODE : CommonConstants.MONITOR_DOWN_CODE;
int matchedRows = jdbcTemplate.update(sql, status, id, status);
if (matchedRows > 0) {
entityManager.getEntityManagerFactory().getCache().evict(Monitor.class, id);
}
} catch (EmptyResultDataAccessException ignored) {
// when query currentStatus result is null
} catch (Exception e) {
log.error("Update monitor status failed for monitor id: {}", id, e);
}
}
}
}
-6
View File
@@ -19,7 +19,6 @@ export class AppComponent implements OnInit {
private router: Router,
private titleSrv: TitleService,
private modalSrv: NzModalService,
private themeService: ThemeService,
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
) {
renderer.setAttribute(el.nativeElement, 'ng-alain-version', VERSION_ALAIN.full);
@@ -49,10 +48,5 @@ export class AppComponent implements OnInit {
this.modalSrv.closeAll();
}
});
// set theme
const storedTheme = localStorage.getItem('theme');
if (storedTheme) {
this.themeService.changeTheme(storedTheme);
}
}
}
@@ -12,6 +12,7 @@ import { catchError, map } from 'rxjs/operators';
import { ICONS } from '../../../style-icons';
import { ICONS_AUTO } from '../../../style-icons-auto';
import { MemoryStorageService } from '../../service/memory-storage.service';
import { ThemeService } from '../../service/theme.service';
import { I18NService } from '../i18n/i18n.service';
@Injectable({
@@ -28,7 +29,8 @@ export class StartupService {
@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService,
private httpClient: HttpClient,
private router: Router,
private storageService: MemoryStorageService
private storageService: MemoryStorageService,
private themeService: ThemeService
) {
iconSrv.addIcon(...ICONS_AUTO, ...ICONS);
}
@@ -86,6 +88,7 @@ export class StartupService {
this.storageService.putData('hierarchy', menuData.data);
this.menuService.resume();
this.titleService.suffix = appData.app.name;
this.themeService.changeTheme(null);
})
);
}
@@ -41,9 +41,6 @@ import { CONSTANTS } from '../../shared/constants';
<div nz-menu-item>
<header-fullscreen></header-fullscreen>
</div>
<div nz-menu-item>
<header-clear-storage></header-clear-storage>
</div>
<div nz-menu-item routerLink="/setting/labels">
<i nz-icon nzType="tag" class="mr-sm"></i>
<span style="margin-left: 4px">{{ 'menu.advanced.labels' | i18n }}</span>
@@ -1,35 +0,0 @@
import { ChangeDetectionStrategy, Component, HostListener, Inject } from '@angular/core';
import { I18NService } from '@core';
import { ALAIN_I18N_TOKEN } from '@delon/theme';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalService } from 'ng-zorro-antd/modal';
@Component({
selector: 'header-clear-storage',
template: `
<i nz-icon class="mr-sm" nzType="tool"></i>
{{ 'menu.clear.local.storage' | i18n }}
`,
host: {
'[class.d-block]': 'true'
},
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderClearStorageComponent {
constructor(
private modalSrv: NzModalService,
private messageSrv: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
) {}
@HostListener('click')
_click(): void {
this.modalSrv.confirm({
nzTitle: this.i18nSvc.fanyi('common.confirm.clear-cache'),
nzOnOk: () => {
localStorage.clear();
this.messageSrv.success(this.i18nSvc.fanyi('common.notify.clear-success'));
}
});
}
}
@@ -129,12 +129,7 @@ export class HeaderUserComponent {
}
logout(): void {
let tmp = this.localStorageSvc.getData(this.notShowAgainKey);
if (tmp === null) {
tmp = 'false';
}
this.localStorageSvc.clear();
this.localStorageSvc.putData(this.notShowAgainKey, tmp);
this.localStorageSvc.clearAuthorization();
this.router.navigateByUrl('/passport/login');
}
-2
View File
@@ -19,7 +19,6 @@ import { NzInputModule } from 'ng-zorro-antd/input';
import { NzSpinModule } from 'ng-zorro-antd/spin';
import { LayoutBasicComponent } from './basic/basic.component';
import { HeaderClearStorageComponent } from './basic/widgets/clear-storage.component';
import { HeaderFullScreenComponent } from './basic/widgets/fullscreen.component';
import { HeaderI18nComponent } from './basic/widgets/i18n.component';
import { HeaderSearchComponent } from './basic/widgets/search.component';
@@ -33,7 +32,6 @@ const HEADER_COMPONENTS = [
HeaderSearchComponent,
HeaderFullScreenComponent,
HeaderI18nComponent,
HeaderClearStorageComponent,
HeaderUserComponent,
HeaderNotifyComponent
];
@@ -67,17 +67,50 @@
flex-direction: column;
gap: 12px;
padding: 16px;
transform-style: preserve-3d;
perspective: 1200px;
}
:root {
--background-color: #fff;
--text-color: #333;
}
[data-theme='dark'] {
--background-color: #1e1e1e;
--text-color: #fff;
}
.alert-card {
background: #fff;
position: relative;
background: var(--background-color);
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-left: 4px solid #ff4d4f;
transition: all 0.3s;
z-index: 1;
&.expanded {
z-index: 2;
}
&.status-firing {
border-left: 4px solid #ff4d4f;
opacity: 0.9;
}
&.status-resolved {
border-left: 4px solid #52c41a;
opacity: 0.7;
}
&.status-pending {
border-left: 4px solid #faad14;
opacity: 0.8;
}
&:hover {
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
z-index: 3;
}
::ng-deep .ant-card-body {
@@ -89,7 +122,7 @@
justify-content: space-between;
align-items: flex-start;
padding-bottom: 12px;
border-bottom: 1px solid #f0f0f0;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
.alert-info {
flex: 1;
@@ -109,7 +142,7 @@
display: flex;
gap: 16px;
margin-top: 8px;
color: #8c8c8c;
color: rgba(0, 0, 0, 0.5);
font-size: 12px;
i {
@@ -142,16 +175,22 @@
.alert-details {
margin-top: 12px;
position: relative;
z-index: 4;
::ng-deep {
.ant-collapse {
background: transparent;
border: none;
position: relative;
z-index: 5;
.ant-collapse-item {
border-radius: 2px;
border: 1px solid #f0f0f0;
border: 1px solid rgba(0, 0, 0, 0.1);
margin-bottom: 8px;
position: relative;
z-index: 6;
&:last-child {
margin-bottom: 0;
@@ -161,9 +200,11 @@
padding: 8px 12px;
align-items: center;
cursor: pointer;
position: relative;
z-index: 7;
&:hover {
background-color: #fafafa;
background-color: rgba(0, 0, 0, 0.05);
}
.ant-collapse-header-text {
@@ -172,19 +213,21 @@
.ant-collapse-extra {
margin: 0;
color: #8c8c8c;
color: rgba(0, 0, 0, 0.5);
font-size: 12px;
}
.alert-content {
font-size: 13px;
color: #333;
color: var(--text-color);
line-height: 1.5;
}
}
.ant-collapse-content {
border-top: 1px solid #f0f0f0;
border-top: 1px solid rgba(0, 0, 0, 0.1);
position: relative;
z-index: 6;
.ant-collapse-content-box {
padding: 12px;
@@ -268,20 +311,6 @@
text-align: right;
}
.alert-card {
&.status-firing {
border-left-color: #ff4d4f;
}
&.status-resolved {
border-left-color: #52c41a;
}
&.status-pending {
border-left-color: #faad14;
}
}
@keyframes slideInFromRight {
0% {
transform: translate3d(120%, 0, 0) scale(0.95) rotate(3deg);
@@ -304,7 +333,6 @@
}
.alert-card {
position: relative;
transition:
transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94),
opacity 0.5s ease-out,
@@ -331,6 +359,7 @@
);
opacity: 0;
animation: slideGlow 1s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
}
&.new-alert {
@@ -365,7 +394,3 @@
.alert-card:nth-child(2) { animation-delay: 0.15s; }
.alert-card:nth-child(3) { animation-delay: 0.2s; }
.alert-card:nth-child(n+4) { animation-delay: 0.25s; }
.alert-cards {
perspective: 1200px;
}
@@ -1,20 +1,32 @@
:root {
--background-color: #fff;
--text-color: #333;
}
[data-theme='dark'] {
--background-color: #1e1e1e;
--text-color: #fff;
}
.alert-integration-container {
display: flex;
height: 100%;
background: #fff;
background: var(--background-color);
border-radius: 4px;
.data-sources {
width: 240px;
border-right: 1px solid #f0f0f0;
padding: 16px;
background: var(--background-color);
h2 {
margin-bottom: 16px;
font-size: 16px;
font-weight: 500;
color: var(--text-color);
}
.source-list {
.source-item {
display: flex;
@@ -23,37 +35,53 @@
cursor: pointer;
border-radius: 4px;
transition: all 0.3s;
&:hover {
background: #f5f5f5;
background: rgba(0, 0, 0, 0.05);
}
&.active {
background: #e6f7ff;
background: rgba(0, 0, 0, 0.1);
}
img {
width: 24px;
height: 24px;
margin-right: 8px;
}
span {
color: #333;
color: var(--text-color);
}
}
}
}
.doc-content {
flex: 1;
padding: 24px;
overflow-y: auto;
background: var(--background-color);
h2 {
margin-bottom: 24px;
font-size: 20px;
font-weight: 500;
color: var(--text-color);
}
}
}
[data-theme='dark'] {
.source-list {
.source-item {
&:hover {
background: rgba(255, 255, 255, 0.1);
}
&.active {
background: rgba(255, 255, 255, 0.2);
}
}
}
}
@@ -17,7 +17,7 @@
~ under the License.
-->
<div class="br-8" style="background-color: snow; padding: 20px; box-shadow: 7px 5px #b421cc">
<div class="br-8" style="background-color: rgb(198 189 189 / 39%); padding: 20px; box-shadow: 7px 5px #b421cc">
<form nz-form [formGroup]="form" (ngSubmit)="submit()" role="form">
<nz-tabset [nzAnimated]="false" class="tabs" (nzSelectChange)="switch($event)">
<nz-tab [nzTitle]="'app.login.tab-login-credentials' | i18n">
@@ -58,7 +58,7 @@ export class SystemConfigComponent implements OnInit {
if (message.code === 0) {
if (message.data) {
this.config = message.data;
this.changeTheme(this.config.theme); // update theme after config is loaded
this.config.theme = this.themeService.getTheme() || 'default';
} else {
this.config = new SystemConfig();
}
@@ -94,6 +94,7 @@ export class SystemConfigComponent implements OnInit {
this.i18nSvc.loadLangData(language).subscribe(res => {
this.i18nSvc.use(language, res);
this.settings.setLayout('lang', language);
this.themeService.setTheme(this.config.theme);
setTimeout(() => this.doc.location.reload());
});
} else {
@@ -105,8 +106,4 @@ export class SystemConfigComponent implements OnInit {
}
);
}
changeTheme(theme: string): void {
this.themeService.changeTheme(theme);
}
}
@@ -1,10 +1,11 @@
@import '@delon/theme/index';
.tag-cards-container {
padding: 24px 0;
.tag-card {
transition: all 0.3s;
border-radius: 8px;
background: #fff;
&:hover {
transform: translateY(-2px);
@@ -23,8 +24,7 @@
.ant-card-actions {
border-radius: 0 0 8px 8px;
background: #fafafa;
border-top: 1px solid #f0f0f0;
border-top: 1px solid rgba(240, 240, 240, 0.5);
min-height: 32px;
> li {
@@ -34,7 +34,7 @@
padding: 4px 0;
&:hover {
color: #1890ff;
color: @primary-color;
}
i {
@@ -60,6 +60,7 @@
font-weight: 500;
line-height: 1.4;
text-align: center;
background: rgba(255, 255, 255, 0.8);
}
}
@@ -57,7 +57,8 @@ export class LocalStorageService {
return localStorage.getItem(AuthorizationConst) != null;
}
public clear() {
localStorage.clear();
public clearAuthorization() {
localStorage.removeItem(AuthorizationConst);
localStorage.removeItem(RefreshTokenConst);
}
}
+4 -8
View File
@@ -36,11 +36,10 @@ export class ThemeService {
return localStorage.getItem(this.themeKey);
}
clearTheme(): void {
localStorage.removeItem(this.themeKey);
}
changeTheme(theme: string): void {
changeTheme(theme: string | null): void {
if (theme == null) {
theme = this.getTheme();
}
const style = this.doc.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
@@ -57,9 +56,6 @@ export class ThemeService {
const compactDom = this.doc.getElementById('compact-theme');
if (compactDom) compactDom.remove();
this.clearTheme();
return;
}
+2
View File
@@ -420,6 +420,8 @@
"common.confirm.delete-batch": "请确认是否批量删除!",
"common.confirm.enable": "请确认是否启用!",
"common.confirm.enable-batch": "请确认是否批量启用!",
"common.copy": "复制到粘贴板",
"common.copy.button": "复制",
"common.disable": "关闭",
"common.edit": "操作",
"common.edit-time": "更新时间",