From 610c5b3fa6798ac5cc2147d810cf05f764e4a5e8 Mon Sep 17 00:00:00 2001 From: Kiefer Chang Date: Mon, 23 Dec 2019 16:03:10 +0800 Subject: [PATCH] mgr/dashboard: Add Orchestrator doc components Create two components for redirecting to Orchestrator Documents: - cd-orchestrator-doc-panel: For displaying an information panel - cd-orchestrator-doc-modal: For displaying an modal contains the information panel Signed-off-by: Kiefer Chang --- .../src/app/ceph/cluster/cluster.module.ts | 4 ++- .../app/shared/api/orchestrator.service.ts | 4 +-- .../shared/components/components.module.ts | 9 +++-- .../orchestrator-doc-modal.component.html | 16 +++++++++ .../orchestrator-doc-modal.component.scss | 0 .../orchestrator-doc-modal.component.spec.ts | 29 +++++++++++++++ .../orchestrator-doc-modal.component.ts | 21 +++++++++++ .../orchestrator-doc-panel.component.html | 5 +++ .../orchestrator-doc-panel.component.scss | 0 .../orchestrator-doc-panel.component.spec.ts | 29 +++++++++++++++ .../orchestrator-doc-panel.component.ts | 33 +++++++++++++++++ .../services/dep-checker.service.spec.ts | 20 +++++++++++ .../shared/services/dep-checker.service.ts | 36 +++++++++++++++++++ 13 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.html create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.scss create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.html create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.scss create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts index 53aae8e28d3..a08d669044b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts @@ -14,6 +14,7 @@ import { TimepickerModule } from 'ngx-bootstrap/timepicker'; import { TooltipModule } from 'ngx-bootstrap/tooltip'; import { TypeaheadModule } from 'ngx-bootstrap/typeahead'; +import { OrchestratorDocModalComponent } from '../../shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component'; import { SharedModule } from '../../shared/shared.module'; import { PerformanceCounterModule } from '../performance-counter/performance-counter.module'; import { CephSharedModule } from '../shared/ceph-shared.module'; @@ -62,7 +63,8 @@ import { ServicesComponent } from './services/services.component'; OsdReweightModalComponent, SilenceMatcherModalComponent, OsdDevicesSelectionModalComponent, - OsdCreationPreviewModalComponent + OsdCreationPreviewModalComponent, + OrchestratorDocModalComponent ], imports: [ CommonModule, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/orchestrator.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/orchestrator.service.ts index 6fbd44d2fa5..cea8d4bccd9 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/orchestrator.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/orchestrator.service.ts @@ -17,8 +17,8 @@ export class OrchestratorService { constructor(private http: HttpClient) {} - status() { - return this.http.get(`${this.url}/status`); + status(): Observable<{ available: boolean; description: string }> { + return this.http.get<{ available: boolean; description: string }>(`${this.url}/status`); } identifyDevice(hostname: string, device: string, duration: number) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts index 6c729a85858..db8b6364e29 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts @@ -28,6 +28,8 @@ import { LanguageSelectorComponent } from './language-selector/language-selector import { LoadingPanelComponent } from './loading-panel/loading-panel.component'; import { ModalComponent } from './modal/modal.component'; import { NotificationsSidebarComponent } from './notifications-sidebar/notifications-sidebar.component'; +import { OrchestratorDocModalComponent } from './orchestrator-doc-modal/orchestrator-doc-modal.component'; +import { OrchestratorDocPanelComponent } from './orchestrator-doc-panel/orchestrator-doc-panel.component'; import { PwdExpirationNotificationComponent } from './pwd-expiration-notification/pwd-expiration-notification.component'; import { RefreshSelectorComponent } from './refresh-selector/refresh-selector.component'; import { SelectBadgesComponent } from './select-badges/select-badges.component'; @@ -77,7 +79,9 @@ import { ViewCacheComponent } from './view-cache/view-cache.component'; ConfigOptionComponent, AlertPanelComponent, FormModalComponent, - PwdExpirationNotificationComponent + PwdExpirationNotificationComponent, + OrchestratorDocPanelComponent, + OrchestratorDocModalComponent ], providers: [], exports: [ @@ -97,7 +101,8 @@ import { ViewCacheComponent } from './view-cache/view-cache.component'; RefreshSelectorComponent, ConfigOptionComponent, AlertPanelComponent, - PwdExpirationNotificationComponent + PwdExpirationNotificationComponent, + OrchestratorDocPanelComponent ], entryComponents: [ ModalComponent, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.html new file mode 100644 index 00000000000..a205f714eed --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.html @@ -0,0 +1,16 @@ + + {{ actionDescription }} {{ itemDescription }} + + + + + + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.spec.ts new file mode 100644 index 00000000000..49fe4385384 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.spec.ts @@ -0,0 +1,29 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { BsModalRef } from 'ngx-bootstrap/modal'; + +import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper'; +import { ComponentsModule } from '../components.module'; +import { OrchestratorDocModalComponent } from './orchestrator-doc-modal.component'; + +describe('OrchestratorDocModalComponent', () => { + let component: OrchestratorDocModalComponent; + let fixture: ComponentFixture; + + configureTestBed({ + imports: [ComponentsModule, HttpClientTestingModule, RouterTestingModule], + providers: [BsModalRef, i18nProviders] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OrchestratorDocModalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.ts new file mode 100644 index 00000000000..91463bfbea1 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component.ts @@ -0,0 +1,21 @@ +import { Component, OnInit } from '@angular/core'; + +import { BsModalRef } from 'ngx-bootstrap/modal'; + +@Component({ + selector: 'cd-orchestrator-doc-modal', + templateUrl: './orchestrator-doc-modal.component.html', + styleUrls: ['./orchestrator-doc-modal.component.scss'] +}) +export class OrchestratorDocModalComponent implements OnInit { + actionDescription: string; + itemDescription: string; + + constructor(public bsModalRef: BsModalRef) {} + + ngOnInit() {} + + onSubmit() { + this.bsModalRef.hide(); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.html new file mode 100644 index 00000000000..5159177ab50 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.html @@ -0,0 +1,5 @@ +Orchestrator is not available. Please consult the + documentation on how to + configure and enable the functionality. diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.spec.ts new file mode 100644 index 00000000000..e2c7935127b --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.spec.ts @@ -0,0 +1,29 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper'; +import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe'; +import { SummaryService } from '../../services/summary.service'; +import { ComponentsModule } from '../components.module'; +import { OrchestratorDocPanelComponent } from './orchestrator-doc-panel.component'; + +describe('OrchestratorDocPanelComponent', () => { + let component: OrchestratorDocPanelComponent; + let fixture: ComponentFixture; + + configureTestBed({ + imports: [ComponentsModule, HttpClientTestingModule, RouterTestingModule], + providers: [CephReleaseNamePipe, SummaryService, i18nProviders] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OrchestratorDocPanelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.ts new file mode 100644 index 00000000000..f2f8b1eb8c9 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/orchestrator-doc-panel/orchestrator-doc-panel.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; + +import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe'; +import { SummaryService } from '../../services/summary.service'; + +@Component({ + selector: 'cd-orchestrator-doc-panel', + templateUrl: './orchestrator-doc-panel.component.html', + styleUrls: ['./orchestrator-doc-panel.component.scss'] +}) +export class OrchestratorDocPanelComponent implements OnInit { + docsUrl: string; + + constructor( + private cephReleaseNamePipe: CephReleaseNamePipe, + private summaryService: SummaryService + ) {} + + ngOnInit() { + const subs = this.summaryService.subscribe((summary: any) => { + if (!summary) { + return; + } + + const releaseName = this.cephReleaseNamePipe.transform(summary.version); + this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/orchestrator_cli/`; + + setTimeout(() => { + subs.unsubscribe(); + }, 0); + }); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.spec.ts new file mode 100644 index 00000000000..7114f283a15 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.spec.ts @@ -0,0 +1,20 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; + +import { BsModalService, ModalModule } from 'ngx-bootstrap/modal'; + +import { configureTestBed } from '../../../testing/unit-test-helper'; +import { OrchestratorService } from '../api/orchestrator.service'; +import { DepCheckerService } from './dep-checker.service'; + +describe('DepCheckerService', () => { + configureTestBed({ + providers: [BsModalService, DepCheckerService, OrchestratorService], + imports: [HttpClientTestingModule, ModalModule.forRoot()] + }); + + it('should be created', () => { + const service: DepCheckerService = TestBed.get(DepCheckerService); + expect(service).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.ts new file mode 100644 index 00000000000..84a0dfa489c --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/dep-checker.service.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@angular/core'; + +import { BsModalService } from 'ngx-bootstrap/modal'; + +import { OrchestratorService } from '../api/orchestrator.service'; +import { OrchestratorDocModalComponent } from '../components/orchestrator-doc-modal/orchestrator-doc-modal.component'; + +@Injectable({ + providedIn: 'root' +}) +export class DepCheckerService { + constructor(private orchService: OrchestratorService, private modalService: BsModalService) {} + + /** + * Check if orchestrator is available. Display an information modal if not. + * If orchestrator is available, then the provided function will be called. + * This helper function can be used with table actions. + * @param {string} actionDescription name of the action. + * @param {string} itemDescription the item's name that the action operates on. + * @param {Function} func the function to be called if orchestrator is available. + */ + checkOrchestratorOrModal(actionDescription: string, itemDescription: string, func: Function) { + this.orchService.status().subscribe((status) => { + if (status.available) { + func(); + } else { + this.modalService.show(OrchestratorDocModalComponent, { + initialState: { + actionDescription: actionDescription, + itemDescription: itemDescription + } + }); + } + }); + } +} -- 2.39.5