This is an automated email from the ASF dual-hosted git repository. gongchao pushed a commit to branch select-monitors-menu in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
commit 9bdd93e2386505ce64d3f9230ce492c30920d665 Author: tomsun28 <[email protected]> AuthorDate: Mon Dec 1 23:16:59 2025 +0800 feat: update add monitors pop selected menus modal Signed-off-by: tomsun28 <[email protected]> --- .../monitor-list/monitor-list.component.html | 10 +- .../monitor-list/monitor-list.component.less | 17 ++- .../monitor-select-menu.component.html | 45 +++--- .../monitor-select-menu.component.less | 157 ++++++++++++++++++--- .../monitor-select-menu.component.ts | 21 +++ 5 files changed, 208 insertions(+), 42 deletions(-) diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html index 0dbd76053d..b980116f17 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html @@ -370,16 +370,17 @@ <nz-modal [(nzVisible)]="appSwitchModalVisible" (nzOnCancel)="onAppSwitchModalCancel()" - nzClosable="false" - nzWidth="30%" + nzClosable="true" + nzWidth="900px" nzWrapClassName="monitor-select-menu-modal" + [nzTitle]="appSwitchModalVisibleType === 1 ? ('monitor.search.app' | i18n) : ('monitor.new-monitor' | i18n)" [nzFooter]="null" [nzOkLoading]="appSearchLoading" + nzCentered > <div *nzModalContent class="-inner-content"> <app-monitor-select-menu - listStyle="border-right: 0px" - [searchPlaceholder]="(appSwitchModalVisibleType === 1 ? 'monitor.search.app' : 'monitor.center.search.placeholder') | i18n" + [searchPlaceholder]="'monitor.center.search.placeholder' | i18n" [loading]="appSearchLoading" [data]="appSearchOrigin" (selectedChanged)="gotoMonitorAddDetail($event)" @@ -387,7 +388,6 @@ <ng-template let-app="item" #prefix> <i nz-icon [nzType]="getAppIconName(app.value)" nzTheme="outline"></i> </ng-template> - <ng-template #suffix>@if (appSwitchModalVisibleType !== 1) {<i nz-icon nzType="right"></i>}</ng-template> </app-monitor-select-menu> </div> </nz-modal> diff --git a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less index 7817988a06..9a288de84b 100644 --- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less +++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.less @@ -2,10 +2,25 @@ ::ng-deep { .monitor-select-menu-modal { + .ant-modal-body { + padding: 0; + max-height: 70vh; + overflow: hidden; + } + + .-inner-content { + height: 70vh; + max-height: 70vh; + } + .ant-spin-container { - max-height: 80vh; + max-height: 70vh; overflow: hidden; } + + app-monitor-select-menu { + height: 100%; + } } } diff --git a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html index fd2c2b472f..44a7ddd46e 100755 --- a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html +++ b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.html @@ -18,7 +18,7 @@ --> <nz-spin [nzSpinning]="loading" style="height: 100%"> - <div style="margin: 8px 8px -4px 8px"> + <div class="search-container"> <app-multi-func-input type="search" [placeholder]="searchPlaceholder || ('common.search' | i18n)" @@ -26,22 +26,29 @@ (valueChange)="filter($event)" /> </div> - <nz-divider></nz-divider> - <ul [style]="'flex: 1; overflow: hidden; overflow-y: auto;' + listStyle" nz-menu nzMode="inline" nzInlineCollapsed="false"> - <li *ngFor="let menuItem of !!search ? dataByFilter : data" nz-submenu [nzTitle]="menuItem[1].label" [nzOpen]="!!search"> - <ul> - <li class="item" nz-menu-item *ngFor="let app of menuItem[1].child" [nzSelected]="app.value === selected"> - <ng-container *ngIf="prefixTemplateRef; else noPrefixContent"> - <ng-template [ngTemplateOutlet]="prefixTemplateRef" [ngTemplateOutletContext]="{ item: app }"></ng-template> - </ng-container> - <ng-template #noPrefixContent></ng-template> - <span class="label" [title]="app.label" (click)="onSelectedChanged(app.value)">{{ app.label }}</span> - <ng-container *ngIf="suffixTemplateRef; else noSuffixContent"> - <ng-template [ngTemplateOutlet]="suffixTemplateRef" [ngTemplateOutletContext]="{ item: app }"></ng-template> - </ng-container> - <ng-template #noSuffixContent></ng-template> - </li> - </ul> - </li> - </ul> + <div class="category-container" [style]="listStyle"> + <div class="category-section" *ngFor="let menuItem of !!search ? dataByFilter : data"> + <div class="category-header"> + <span> + <i nz-icon [nzType]="getCategoryIcon(menuItem[0])" nzTheme="outline"></i> + </span> + <span class="category-title">{{ menuItem[1].label }}</span> + <span class="category-count">{{ menuItem[1].child.length }}</span> + </div> + <div class="category-items"> + <div + class="monitor-type-card" + *ngFor="let app of menuItem[1].child" + [class.selected]="app.value === selected" + (click)="onSelectedChanged(app.value)" + > + <span class="card-label">{{ app.label }}</span> + </div> + </div> + </div> + <div class="empty-state" *ngIf="(!!search ? dataByFilter : data)?.length === 0"> + <i nz-icon nzType="inbox" nzTheme="outline"></i> + <span>{{ 'common.no-data' | i18n }}</span> + </div> + </div> </nz-spin> diff --git a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less index a723c9414e..89e8fc707f 100755 --- a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less +++ b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.less @@ -1,31 +1,154 @@ +@import '~src/styles/theme'; + :host ::ng-deep { + .ant-spin-container { + height: 100%; + display: flex; + overflow: hidden; + flex-direction: column; + } +} - .item{ - padding-left: 32px!important; +:host { + display: block; + height: 100%; - .ant-menu-title-content { - gap: 8px; - display: flex; - align-items: center; + .search-container { + padding: 16px 16px 0 16px; + } - :first-child { - flex-shrink: 0; - } + .category-container { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + padding: 16px; + } - .label { - flex: 1; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } + .category-section { + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; } } - .ant-spin-container { - height: 100%; + .category-header { display: flex; + align-items: center; + gap: 10px; + margin-bottom: 12px; + padding-bottom: 10px; + border-bottom: 1px solid #f0f0f0; + } + + .category-title { + font-size: 15px; + font-weight: 600; + color: #1f1f1f; + } + + .category-count { + font-size: 12px; + color: #8c8c8c; + background: #f5f5f5; + padding: 2px 8px; + border-radius: 10px; + margin-left: auto; + } + + .category-items { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 10px; + } + + .monitor-type-card { + display: flex; + align-items: center; + justify-content: center; + padding: 10px 12px; + background: #fafafa; + border: 1px solid #e8e8e8; + border-radius: 6px; + cursor: pointer; + transition: all 0.2s ease; + text-align: center; + + &:hover { + border-color: @primary-color; + background: #e6f4ff; + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15); + } + + &.selected { + border-color: @primary-color; + background: #e6f4ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); + } + } + + .card-label { + font-size: 13px; + color: #333; overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + line-height: 1.4; + } + + .empty-state { + display: flex; flex-direction: column; + align-items: center; + justify-content: center; + padding: 48px 0; + color: #8c8c8c; + + i { + font-size: 48px; + margin-bottom: 12px; + } } +} + +// Dark theme support +[data-theme='dark'] { + :host { + .category-header { + border-bottom-color: #303030; + } + + .category-title { + color: #d9d9d9; + } + + .category-count { + background: #303030; + color: #a0a0a0; + } + + .monitor-type-card { + background: #1f1f1f; + border-color: #303030; + &:hover { + border-color: @primary-color; + background: #111d2c; + } + + &.selected { + border-color: @primary-color; + background: #111d2c; + } + } + + .card-label { + color: #d9d9d9; + } + + .empty-state { + color: #6c6c6c; + } + } } diff --git a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts index 20315dea20..89f42e3555 100755 --- a/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts +++ b/web-app/src/app/shared/components/monitor-select-menu/monitor-select-menu.component.ts @@ -51,4 +51,25 @@ export class MonitorSelectMenuComponent { onSelectedChanged(selected: string) { this.selectedChanged.emit(selected); } + + getCategoryIcon(category: string): string { + const iconMap: Record<string, string> = { + os: 'desktop', + webserver: 'global', + bigdata: 'cluster', + cache: 'database', + service: 'api', + server: 'hdd', + mid: 'deployment-unit', + db: 'database', + custom: 'tool', + llm: 'robot', + network: 'wifi', + cn: 'cloud-server', + cicd: 'branches', + auto: 'thunderbolt', + program: 'code' + }; + return iconMap[category] || 'appstore'; + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
