]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/dashboard: Show info button for crush rules in pool form
authorStephan Müller <smueller@suse.com>
Wed, 24 Oct 2018 14:02:24 +0000 (16:02 +0200)
committerStephan Müller <smueller@suse.com>
Fri, 9 Nov 2018 08:40:39 +0000 (09:40 +0100)
Signed-off-by: Stephan Müller <smueller@suse.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form-data.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts

index 971aece141328b87b863d9f585081e3fce3df40a..c87f2c059e2ac1de7e76552e6cc004f4e5172f7e 100644 (file)
@@ -7,6 +7,7 @@ import { Pool } from '../pool';
 export class PoolFormData {
   poolTypes = ['erasure', 'replicated'];
   erasureInfo = false;
+  crushInfo = false;
   applications = {
     selected: [],
     available: [
index fe04c437fe1cda4784944fe32d71395d9f0c5c23..4d99d8e84c15e279dee6b3403d30f098b6e6df7f 100644 (file)
           </div>
 
           <!-- Crush ruleset selection -->
-          <ng-template #crushSteps>
-            <ng-container *ngIf="form.getValue('crushRule')">
-              <div class="crush-rule-steps">
-                <ol>
-                  <li *ngFor="let step of form.get('crushRule').value.steps">
-                    {{ describeCrushStep(step) }}
-                  </li>
-                </ol>
-              </div>
-            </ng-container>
-          </ng-template>
           <div class="form-group"
                [ngClass]="{'has-error': form.showError('crushRule', formDir)}"
                *ngIf="form.getValue('poolType') && current.rules.length > 0">
             <label class="control-label col-sm-3"
-                   for="crushSet"
+                   for="crushRule"
                    i18n>
               Crush ruleset
             </label>
-            <div class="col-sm-9"
-                 [popover]="crushSteps"
-                 popoverTitle="Steps"
-                 triggers="mouseenter:mouseleave">
-              <select class="form-control"
-                      id="crushSet"
-                      formControlName="crushRule"
-                      name="crushSet">
-                <option i18n
-                        [ngValue]="null">
-                  -- Select a crush rule --
-                </option>
-                <option *ngFor="let rule of current.rules"
-                        [ngValue]="rule">
-                  {{ rule.rule_name }}
-                </option>
-              </select>
+            <div class="col-sm-9">
+              <div class="input-group">
+                <select class="form-control"
+                        id="crushRule"
+                        formControlName="crushRule"
+                        name="crushSet">
+                  <option i18n
+                          [ngValue]="null">
+                    -- Select a crush rule --
+                  </option>
+                  <option *ngFor="let rule of current.rules"
+                          [ngValue]="rule">
+                    {{ rule.rule_name }}
+                  </option>
+                </select>
+                <span class="input-group-btn">
+                  <button class="btn btn-default"
+                          [ngClass]="{'active': data.crushInfo}"
+                          id="crush-info-button"
+                          type="button"
+                          (click)="data.crushInfo = !data.crushInfo">
+                    <i class="fa fa-question-circle"
+                       aria-hidden="true"></i>
+                  </button>
+                </span>
+              </div>
+              <span class="help-block"
+                    id="crush-info-block"
+                    *ngIf="data.crushInfo && form.getValue('crushRule')">
+                <tabset>
+                  <tab i18n-heading heading="Crush rule" class="crush-rule-info">
+                    <cd-table-key-value [renderObjects]="true"
+                                        [data]="form.getValue('crushRule')"
+                                        [autoReload]="false">
+                    </cd-table-key-value>
+                  </tab>
+                  <tab i18n-heading heading="Crush steps" class="crush-rule-steps">
+                    <ol>
+                      <li *ngFor="let step of form.get('crushRule').value.steps">
+                        {{ describeCrushStep(step) }}
+                      </li>
+                    </ol>
+                  </tab>
+                </tabset>
+              </span>
               <span class="help-block"
                     i18n
                     *ngIf="form.showError('crushRule', formDir, 'tooFewOsds')">
index 361f8e6d187ecc25543fe647da0653024db43c44..5770d240f5ea817f9db772e7b32b62c7a9a0f8e8 100644 (file)
@@ -7,6 +7,7 @@ import { RouterTestingModule } from '@angular/router/testing';
 
 import { ToastModule } from 'ng2-toastr';
 import { BsModalService } from 'ngx-bootstrap/modal';
+import { TabsModule } from 'ngx-bootstrap/tabs';
 import { of } from 'rxjs';
 
 import { configureTestBed, FormHelper } from '../../../../testing/unit-test-helper';
@@ -127,6 +128,7 @@ describe('PoolFormComponent', () => {
       HttpClientTestingModule,
       RouterTestingModule.withRoutes(routes),
       ToastModule.forRoot(),
+      TabsModule.forRoot(),
       PoolModule
     ],
     providers: [
@@ -734,6 +736,30 @@ describe('PoolFormComponent', () => {
     });
   });
 
+  describe('crushRule', () => {
+    beforeEach(() => {
+      createCrushRule({ name: 'replicatedRule' });
+      fixture.detectChanges();
+      formHelper.setValue('poolType', 'replicated');
+      fixture.detectChanges();
+    });
+
+    it('should not show info per default', () => {
+      formHelper.expectElementVisible(fixture, '#crushRule', true);
+      formHelper.expectElementVisible(fixture, '#crush-info-block', false);
+    });
+
+    it('should show info if the info button is clicked', () => {
+      fixture.detectChanges();
+      const infoButton = fixture.debugElement.query(By.css('#crush-info-button'));
+      infoButton.triggerEventHandler('click', null);
+      expect(component.data.crushInfo).toBeTruthy();
+      fixture.detectChanges();
+      expect(infoButton.classes['active']).toBeTruthy();
+      formHelper.expectIdElementsVisible(fixture, ['crushRule', 'crush-info-block'], true);
+    });
+  });
+
   describe('erasure code profile', () => {
     const setSelectedEcp = (name: string) => {
       formHelper.setValue('erasureProfile', { name: name });