<div>
+ <cd-refresh-selector></cd-refresh-selector>
<tabset *ngIf="hasGrafana">
<tab i18n-heading
heading="Health">
import { Permissions } from '../../../shared/models/permissions';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
import { FeatureTogglesService } from '../../../shared/services/feature-toggles.service';
+import { RefreshIntervalService } from '../../../shared/services/refresh-interval.service';
import { SharedModule } from '../../../shared/shared.module';
import { PgCategoryService } from '../../shared/pg-category.service';
import { HealthPieColor } from '../health-pie/health-pie-color.enum';
providers: [
i18nProviders,
{ provide: AuthStorageService, useValue: fakeAuthStorageService },
- PgCategoryService
+ PgCategoryService,
+ RefreshIntervalService
]
});
import { I18n } from '@ngx-translate/i18n-polyfill';
import * as _ from 'lodash';
+import { Subscription } from 'rxjs/Subscription';
import { HealthService } from '../../../shared/api/health.service';
import { Permissions } from '../../../shared/models/permissions';
FeatureTogglesMap$,
FeatureTogglesService
} from '../../../shared/services/feature-toggles.service';
+import { RefreshIntervalService } from '../../../shared/services/refresh-interval.service';
import { PgCategoryService } from '../../shared/pg-category.service';
import { HealthPieColor } from '../health-pie/health-pie-color.enum';
})
export class HealthComponent implements OnInit, OnDestroy {
healthData: any;
- interval: number;
+ interval = new Subscription();
permissions: Permissions;
enabledFeature$: FeatureTogglesMap$;
private i18n: I18n,
private authStorageService: AuthStorageService,
private pgCategoryService: PgCategoryService,
- private featureToggles: FeatureTogglesService
+ private featureToggles: FeatureTogglesService,
+ private refreshIntervalService: RefreshIntervalService
) {
this.permissions = this.authStorageService.getPermissions();
this.enabledFeature$ = this.featureToggles.get();
ngOnInit() {
this.getHealth();
- this.interval = window.setInterval(() => {
+ this.interval = this.refreshIntervalService.intervalData$.subscribe(() => {
this.getHealth();
- }, 5000);
+ });
}
ngOnDestroy() {
- clearInterval(this.interval);
+ this.interval.unsubscribe();
}
getHealth() {
import { LanguageSelectorComponent } from './language-selector/language-selector.component';
import { LoadingPanelComponent } from './loading-panel/loading-panel.component';
import { ModalComponent } from './modal/modal.component';
+import { RefreshSelectorComponent } from './refresh-selector/refresh-selector.component';
import { SelectBadgesComponent } from './select-badges/select-badges.component';
import { SelectComponent } from './select/select.component';
import { SparklineComponent } from './sparkline/sparkline.component';
WarningPanelComponent,
LanguageSelectorComponent,
GrafanaComponent,
- SelectComponent
+ SelectComponent,
+ RefreshSelectorComponent
],
providers: [],
exports: [
WarningPanelComponent,
LanguageSelectorComponent,
GrafanaComponent,
- SelectComponent
+ SelectComponent,
+ RefreshSelectorComponent
],
entryComponents: [ModalComponent, CriticalConfirmationModalComponent, ConfirmationModalComponent]
})
--- /dev/null
+<div class="row">
+ <div class="col-xs-5 col-sm-2 refresh-selector">
+ <label class="control-label col-xs-5 col-sm-5"
+ for="refreshInterval">
+ <span i18n>Refresh</span>
+ </label>
+ <div class="col-xs-7 col-sm-7">
+ <select id="refreshInterval"
+ name="refreshInterval"
+ class="form-control"
+ (change)="changeRefreshInterval($event.target.value)"
+ [(ngModel)]="selectedInterval">
+ <option *ngFor="let key of intervalKeys"
+ [value]="intervalList[key]">{{ key }}</option>
+ </select>
+ </div>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+.refresh-selector {
+ padding: 0;
+ float: right;
+ margin-right: 60px;
+
+ * {
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ label {
+ padding: 10px 10px 0 0;
+ text-align: right;
+ margin: 0;
+ }
+
+ @media (min-width: 500px) and (max-width: 767px) {
+ width: 24vw;
+ }
+ @media (min-width: 1200px) {
+ width: 12vw;
+ }
+ @media (min-width: 1400px) {
+ width: 10vw;
+ }
+}
--- /dev/null
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+
+import { RefreshIntervalService } from '../../services/refresh-interval.service';
+import { RefreshSelectorComponent } from './refresh-selector.component';
+
+describe('RefreshSelectorComponent', () => {
+ let component: RefreshSelectorComponent;
+ let fixture: ComponentFixture<RefreshSelectorComponent>;
+
+ configureTestBed({
+ imports: [FormsModule],
+ declarations: [RefreshSelectorComponent],
+ providers: [RefreshIntervalService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RefreshSelectorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, OnInit } from '@angular/core';
+
+import { RefreshIntervalService } from '../../services/refresh-interval.service';
+
+@Component({
+ selector: 'cd-refresh-selector',
+ templateUrl: './refresh-selector.component.html',
+ styleUrls: ['./refresh-selector.component.scss']
+})
+export class RefreshSelectorComponent implements OnInit {
+ selectedInterval: number;
+ intervalList: { [key: string]: number } = {
+ '5 s': 5000,
+ '10 s': 10000,
+ '15 s': 15000,
+ '30 s': 30000,
+ '1 min': 60000,
+ '3 min': 180000,
+ '5 min': 300000
+ };
+ intervalKeys = Object.keys(this.intervalList);
+
+ constructor(private refreshIntervalService: RefreshIntervalService) {}
+
+ ngOnInit() {
+ this.selectedInterval = this.refreshIntervalService.getRefreshInterval() || 5000;
+ }
+
+ changeRefreshInterval(interval: number) {
+ this.refreshIntervalService.setRefreshInterval(interval);
+ }
+}
--- /dev/null
+import { fakeAsync, tick } from '@angular/core/testing';
+
+import { RefreshIntervalService } from './refresh-interval.service';
+
+describe('RefreshIntervalService', () => {
+ let service: RefreshIntervalService;
+
+ beforeEach(() => {
+ service = new RefreshIntervalService();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should initial private interval time right', () => {
+ sessionStorage.setItem('dashboard_interval', '10000');
+ service = new RefreshIntervalService();
+ expect(service.getRefreshInterval()).toBe(10000);
+ });
+
+ describe('setRefreshInterval', () => {
+ let notifyCount: number;
+
+ it('should send notification to component at correct interval time when interval changed', fakeAsync(() => {
+ service.intervalData$.subscribe(() => {
+ notifyCount++;
+ });
+
+ notifyCount = 0;
+ service.setRefreshInterval(10000);
+ tick(10000);
+ expect(service.getRefreshInterval()).toBe(10000);
+ expect(notifyCount).toBe(1);
+
+ notifyCount = 0;
+ service.setRefreshInterval(30000);
+ tick(30000);
+ expect(service.getRefreshInterval()).toBe(30000);
+ expect(notifyCount).toBe(1);
+
+ service.ngOnDestroy();
+ }));
+ });
+});
--- /dev/null
+import { Injectable, OnDestroy } from '@angular/core';
+
+import { BehaviorSubject, interval, Subscription } from 'rxjs';
+
+import { ServicesModule } from './services.module';
+@Injectable({
+ providedIn: ServicesModule
+})
+export class RefreshIntervalService implements OnDestroy {
+ private intervalTime: number;
+ // Observable sources
+ private intervalDataSource = new BehaviorSubject(null);
+ private intervalSubscription: Subscription;
+ // Observable streams
+ intervalData$ = this.intervalDataSource.asObservable();
+
+ constructor() {
+ const initialInterval = parseInt(sessionStorage.getItem('dashboard_interval'), 10) || 5000;
+ this.setRefreshInterval(initialInterval);
+ }
+
+ setRefreshInterval(newInterval: number) {
+ this.intervalTime = newInterval;
+ sessionStorage.setItem('dashboard_interval', newInterval.toString());
+
+ if (this.intervalSubscription) {
+ this.intervalSubscription.unsubscribe();
+ }
+ this.intervalSubscription = interval(this.intervalTime).subscribe(() =>
+ this.intervalDataSource.next(this.intervalTime)
+ );
+ }
+
+ getRefreshInterval() {
+ return this.intervalTime;
+ }
+
+ ngOnDestroy() {
+ if (this.intervalSubscription) {
+ this.intervalSubscription.unsubscribe();
+ }
+ }
+}
<context context-type="sourcefile">app/shared/components/grafana/grafana.component.html</context>
<context context-type="linenumber">35</context>
</context-group>
+ </trans-unit><trans-unit id="c8d1785038d461ec66b5799db21864182b35900a" datatype="html">
+ <source>Refresh</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">app/shared/components/refresh-selector/refresh-selector.component.html</context>
+ <context context-type="linenumber">5</context>
+ </context-group>
</trans-unit><trans-unit id="012741ee52b3c050e4a977c37cc2334f7974f141" datatype="html">
<source>Failed to load data.</source>
<context-group purpose="location">
<source>Health</source>
<context-group purpose="location">
<context context-type="sourcefile">app/ceph/dashboard/dashboard/dashboard.component.html</context>
- <context context-type="linenumber">4</context>
+ <context context-type="linenumber">5</context>
</context-group>
</trans-unit><trans-unit id="61e0f26d843eec0b33ff475e111b0c2f7a80b835" datatype="html">
<source>Statistics</source>
<context-group purpose="location">
<context context-type="sourcefile">app/ceph/dashboard/dashboard/dashboard.component.html</context>
- <context context-type="linenumber">8</context>
+ <context context-type="linenumber">9</context>
</context-group>
</trans-unit><trans-unit id="f8f74e5f683012b9c0702b1446011c6b9158bc67" datatype="html">
<source>Please consult the <x id="START_LINK" ctype="x-a" equiv-text="<a>"/>documentation<x id="CLOSE_LINK" ctype="x-a" equiv-text="</a>"/>