@let data=(data$ | async);
@let hwEnabled = (enabled$ | async);
@let hwSections = (sections$ | async);
+@let telemetryEnabled = (telemetryEnabled$ | async);
@let colorClass="overview-health-card-status--" + vm?.clusterHealth?.icon;
source="fsid">
</cd-copy-2-clipboard-button>
</div>
- <cds-icon-button
- type="button"
- kind="ghost"
- size="sm"
- description="Check logs"
- i18n-description
- [routerLink]="['/logs']">
- <cd-icon type="dataViewAlt"></cd-icon>
- </cds-icon-button>
+ <ng-template #telemetryDescription>
+ <div class="cds--type-heading-compact-01 cds-mb-2"
+ i18n>Support & diagnostics</div>
+ <div cdsStack="horizontal"
+ [gap]="10">
+ <span i18n>Telemetry</span>
+ <span>
+ @if (telemetryEnabled) {
+ <cd-icon type="success"></cd-icon>
+ <span i18n>on</span>
+ } @else {
+ <cd-icon type="infoCircle"></cd-icon>
+ <span i18n>off</span>
+ }
+ </span>
+ </div>
+ </ng-template>
+ <div cdsStack="horizontal"
+ [gap]="2">
+ <cds-icon-button
+ type="button"
+ kind="ghost"
+ size="sm"
+ [description]="telemetryDescription">
+ <cd-icon type="cloudMonitoring"></cd-icon>
+ </cds-icon-button>
+ <cds-icon-button
+ type="button"
+ kind="ghost"
+ size="sm"
+ description="Check logs"
+ i18n-description
+ [routerLink]="['/logs']">
+ <cd-icon type="dataViewAlt"></cd-icon>
+ </cds-icon-button>
+ </div>
</ng-template>
} @else {
<cds-skeleton-text
import { ProductiveCardComponent } from '~/app/shared/components/productive-card/productive-card.component';
import { PipesModule } from '~/app/shared/pipes/pipes.module';
import { HardwareService } from '~/app/shared/api/hardware.service';
+import { HealthService } from '~/app/shared/api/health.service';
import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
getSummary: jest.fn(() => of(null))
};
+ const mockHealthService = {
+ getTelemetryStatus: jest.fn(() => of(false))
+ };
+
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
{ provide: AuthStorageService, useValue: mockAuthStorageService },
{ provide: MgrModuleService, useValue: mockMgrModuleService },
{ provide: HardwareService, useValue: mockHardwareService },
+ { provide: HealthService, useValue: mockHealthService },
provideRouter([])
]
}).compileComponents();
import { catchError, filter, map, shareReplay, startWith, switchMap } from 'rxjs/operators';
import { HealthCardTabSection, HealthCardVM } from '~/app/shared/models/overview';
import { HardwareService } from '~/app/shared/api/hardware.service';
+import { HealthService } from '~/app/shared/api/health.service';
import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.service';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
export class OverviewHealthCardComponent {
private readonly summaryService = inject(SummaryService);
private readonly upgradeService = inject(UpgradeService);
+ private readonly healthService = inject(HealthService);
private readonly hardwareService = inject(HardwareService);
private readonly mgrModuleService = inject(MgrModuleService);
private readonly refreshIntervalService = inject(RefreshIntervalService);
shareReplay({ bufferSize: 1, refCount: true })
);
+ readonly telemetryEnabled$: Observable<boolean> = this.healthService.getTelemetryStatus().pipe(
+ map((enabled: any) => !!enabled),
+ catchError(() => of(false)),
+ shareReplay({ bufferSize: 1, refCount: true })
+ );
+
readonly sections$: Observable<HwRowVM[][] | null> = this.hardwareRows$.pipe(
map((rows) => {
if (!rows) return null;
let component: OverviewComponent;
let fixture: ComponentFixture<OverviewComponent>;
- let mockHealthService: { getHealthSnapshot: jest.Mock };
+ let mockHealthService: { getHealthSnapshot: jest.Mock; getTelemetryStatus: jest.Mock };
let mockRefreshIntervalService: { intervalData$: Subject<void> };
let mockOverviewStorageService: {
getTrendData: jest.Mock;
refreshPrometheusUsable: jest.fn().mockReturnValue(of(true))
};
- mockHealthService = { getHealthSnapshot: jest.fn() };
+ mockHealthService = {
+ getHealthSnapshot: jest.fn(),
+ getTelemetryStatus: jest.fn().mockReturnValue(of(false))
+ };
mockRefreshIntervalService = { intervalData$: new Subject<void>() };
mockOverviewStorageService = {
import Locked16 from '@carbon/icons/es/locked/16';
import WebServicesCluster20 from '@carbon/icons/es/web-services--cluster/20';
import WebServicesCluster32 from '@carbon/icons/es/web-services--cluster/32';
+import CloudMonitoring16 from '@carbon/icons/es/cloud--monitoring/16';
import { TearsheetStepComponent } from './tearsheet-step/tearsheet-step.component';
import { PageHeaderComponent } from './page-header/page-header.component';
CaretRight16,
Locked16,
WebServicesCluster20,
- WebServicesCluster32
+ WebServicesCluster32,
+ CloudMonitoring16
]);
}
}
arrowUpRight = 'arrow--up-right',
inProgress = 'in-progress',
arrowDown = 'arrow--down',
- locked = 'locked' // Access denied, locked state
+ locked = 'locked', // Access denied, locked state
+ cloudMonitoring = 'cloud--monitoring'
}
export enum IconSize {
angleDoubleRight: 'chevron--right',
leftArrow: 'caret--left',
rightArrow: 'caret--right',
- locked: 'locked'
+ locked: 'locked',
+ cloudMonitoring: 'cloud--monitoring'
} as const;
export const EMPTY_STATE_IMAGE = {