-<cd-productive-card>
+<cd-productive-card class="overview-alerts-card">
@if (vm$ | async; as vm) {
<ng-template #header>
<h2 class="cds--type-heading-compact-02"
.overview-alerts-card {
+ // height: 100%;
&-badges {
display: flex;
align-items: center;
margin-top: var(--cds-spacing-02);
color: var(--cds-text-secondary);
}
+
+ .cds--tile {
+ min-block-size: 0;
+ height: 100%;
+ }
}
-import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';
+import {
+ ChangeDetectionStrategy,
+ Component,
+ OnInit,
+ ViewEncapsulation,
+ inject
+} from '@angular/core';
import { CommonModule } from '@angular/common';
import { combineLatest } from 'rxjs';
],
templateUrl: './overview-alerts-card.component.html',
styleUrl: './overview-alerts-card.component.scss',
- changeDetection: ChangeDetectionStrategy.OnPush
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None
})
export class OverviewAlertsCardComponent implements OnInit {
private readonly prometheusAlertService = inject(PrometheusAlertService);
<!-- SYSTEM TAB -->
@if(vm?.overallSystemSev) {
<div class="overview-health-card-tab"
- [ngClass]="{'overview-health-card-tab-selected': activeSection === 'system'}">
+ [class.overview-health-card-tab-selected]="activeSection === 'system'">
<div class="cds-mb-1"><cd-icon
[type]="vm?.overallSystemSev"></cd-icon></div>
<cds-tooltip-definition
i18n-description>
<span
class="cds-mr-1"
- [ngClass]="{'cds--type-heading-compact-01': activeSection === 'system'}"
+ [class.cds--type-heading-compact-01]="activeSection === 'system'"
i18n>
Systems
</span>
i18n>Some cluster components are degraded and may require attention.</p>
<div cdsStack="horizontal"
[gap]="8">
- <div class="overview-health-card-tab-content-item cds-pr-8">
- <span>
- <cd-icon [type]="vm?.mon?.severity"></cd-icon>
- <span class="cds--type-body-compact-01 cds-ml-3">Monitor</span>
+ @for (item of healthItems; track item.key; let isLast = $last) {
+ <div class="cds-pr-8"
+ [class.overview-health-card-tab-content-item]="!isLast">
+ <span class="overview-health-card-icon-and-text">
+ <cd-icon [type]="vm?.[item.key]?.severity"></cd-icon>
+ <span class="cds--type-body-compact-01">
+ {{ item.label }}
+ </span>
</span>
- <p class="cds--type-label-01 cds-mt-3 cds-mb-0 overview-health-card-secondary-text">Quorum: {{vm?.mon?.value}}</p>
- </div>
- <div class="overview-health-card-tab-content-item cds-pr-8">
- <span>
- <cd-icon [type]="vm?.mgr?.severity"></cd-icon>
- <span class="cds--type-body-compact-01 cds-ml-3">Manager</span>
- </span>
- <p class="cds--type-label-01 cds-mt-3 cds-mb-0 overview-health-card-secondary-text">{{vm?.mgr?.value}}</p>
- </div>
- <div class="overview-health-card-tab-content-item cds-pr-8">
- <span>
- <cd-icon [type]="vm?.osd?.severity"></cd-icon>
- <span class="cds--type-body-compact-01 cds-ml-3"
- i18n>OSD</span>
- </span>
- <p class="cds--type-label-01 cds-mt-3 cds-mb-0 overview-health-card-secondary-text">{{vm?.osd?.value}}</p>
- </div>
- <div>
- <span>
- <cd-icon [type]="vm?.hosts?.severity"></cd-icon>
- <span class="cds--type-body-compact-01 cds-ml-3">Nodes</span>
- </span>
- <p class="cds--type-label-01 cds-mt-3 cds-mb-0 overview-health-card-secondary-text">{{vm?.hosts?.value}}</p>
+ <p class="cds--type-label-01 cds-mt-3 cds-mb-0 overview-health-card-secondary-text">
+ {{ vm?.[item.key]?.value }}
+ </p>
</div>
+ }
</div>
</div>
</ng-container>
max-block-size: fit-content;
}
+ &-icon-and-text {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--cds-spacing-03);
+ }
+
// Overrides
.clipboard-btn {
padding: var(--cds-spacing-02);
color: var(--cds-link-primary);
border-block-end: 1px dotted var(--cds-link-primary);
}
+
+ &-icon-and-text cd-icon svg {
+ display: block;
+ }
}
type TabSection = 'system' | 'hardware' | 'resiliency';
+interface HealthItemConfig {
+ key: 'mon' | 'mgr' | 'osd' | 'hosts';
+ label: string;
+ prefix?: string;
+ i18n?: boolean;
+}
+
@Component({
selector: 'cd-overview-health-card',
imports: [
@Output() viewIncidents = new EventEmitter<void>();
activeSection: TabSection | null = null;
+ healthItems: HealthItemConfig[] = [
+ { key: 'mon', label: $localize`Monitor` },
+ { key: 'mgr', label: $localize`Manager` },
+ { key: 'osd', label: $localize`OSD` },
+ { key: 'hosts', label: $localize`Nodes` }
+ ];
toggleSection(section: TabSection) {
this.activeSection = this.activeSection === section ? null : section;
@let health = (healthCardVm$ | async);
<div cdsGrid
[fullWidth]="true"
+ [narrow]="true"
class="cds-mt-5 cds-mb-5">
<div cdsRow>
<div cdsCol
health: healthDisplay,
- mon: { value: `${monQuorum}/${monTotal}`, severity: SeverityIconMap[monSev] },
- mgr: { value: `${mgrActive} active, ${mgrStandby} standby`, severity: SeverityIconMap[mgrSev] },
- osd: { value: `${osdUp}/${osdTotal} in/up`, severity: SeverityIconMap[osdSev] },
+ mon: { value: $localize`Quorum: ${monQuorum}/${monTotal}`, severity: SeverityIconMap[monSev] },
+ mgr: {
+ value: $localize`${mgrActive} active, ${mgrStandby} standby`,
+ severity: SeverityIconMap[mgrSev]
+ },
+ osd: { value: $localize`${osdUp}/${osdTotal} in/up`, severity: SeverityIconMap[osdSev] },
hosts: {
- value: `${hostsAvailable} / ${hostsTotal} available`,
+ value: $localize`${hostsAvailable} / ${hostsTotal} available`,
severity: SeverityIconMap[hostsSev]
}
};