File

src/app/ceph/block/rbd-configuration-form/rbd-configuration-form.component.ts

Implements

OnInit

Metadata

selector cd-rbd-configuration-form
styleUrls ./rbd-configuration-form.component.scss
templateUrl ./rbd-configuration-form.component.html

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(formatterService: FormatterService, rbdConfigurationService: RbdConfigurationService)
Parameters :
Name Type Optional
formatterService FormatterService No
rbdConfigurationService RbdConfigurationService No

Inputs

form
Type : CdFormGroup
initializeData
Type : EventEmitter<literal type>

Outputs

changes
Type : EventEmitter

Methods

Private createConfigurationFormGroup
createConfigurationFormGroup()

Dynamically create form controls.

Returns : any
getDirtyValues
getDirtyValues(includeLocalValues, localFieldType?: RbdConfigurationSourceField)
Parameters :
Name Type Optional Default value
includeLocalValues No false
localFieldType RbdConfigurationSourceField Yes
Returns : {}
isDisabled
isDisabled(optionName: string)
Parameters :
Name Type Optional
optionName string No
Returns : any
ngOnInit
ngOnInit()
Returns : void
reset
reset(optionName: string)

Reset the value. The inherited value will be used instead.

Parameters :
Name Type Optional
optionName string No
Returns : void
toggleSectionVisibility
toggleSectionVisibility(className)
Parameters :
Name Optional
className No
Returns : void

Properties

configurationType
Default value : RbdConfigurationType
Public formatterService
Type : FormatterService
initialData
Type : RbdConfigurationEntry[]
ngDataReady
Default value : new EventEmitter<any>()
Public rbdConfigurationService
Type : RbdConfigurationService
sectionVisibility
Type : literal type
Default value : {}
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';

import { CdFormGroup } from '../../../shared/forms/cd-form-group';
import {
  RbdConfigurationEntry,
  RbdConfigurationSourceField,
  RbdConfigurationType
} from '../../../shared/models/configuration';
import { FormatterService } from '../../../shared/services/formatter.service';
import { RbdConfigurationService } from '../../../shared/services/rbd-configuration.service';

@Component({
  selector: 'cd-rbd-configuration-form',
  templateUrl: './rbd-configuration-form.component.html',
  styleUrls: ['./rbd-configuration-form.component.scss']
})
export class RbdConfigurationFormComponent implements OnInit {
  @Input()
  form: CdFormGroup;
  @Input()
  initializeData: EventEmitter<{
    initialData: RbdConfigurationEntry[];
    sourceType: RbdConfigurationSourceField;
  }>;
  @Output()
  changes = new EventEmitter<any>();
  ngDataReady = new EventEmitter<any>();
  initialData: RbdConfigurationEntry[];
  configurationType = RbdConfigurationType;
  sectionVisibility: { [key: string]: boolean } = {};

  constructor(
    public formatterService: FormatterService,
    public rbdConfigurationService: RbdConfigurationService
  ) {}

  ngOnInit() {
    const configFormGroup = this.createConfigurationFormGroup();
    this.form.addControl('configuration', configFormGroup);

    // Listen to changes and emit the values to the parent component
    configFormGroup.valueChanges.subscribe(() => {
      this.changes.emit(this.getDirtyValues.bind(this));
    });

    if (this.initializeData) {
      this.initializeData.subscribe((data) => {
        this.initialData = data.initialData;
        const dataType = data.sourceType;

        this.rbdConfigurationService.getWritableOptionFields().forEach((option) => {
          const optionData = data.initialData.filter((entry) => entry.name === option.name).pop();
          if (optionData && optionData['source'] === dataType) {
            this.form.get(`configuration.${option.name}`).setValue(optionData['value']);
          }
        });
        this.ngDataReady.emit();
      });
    }

    this.rbdConfigurationService
      .getWritableSections()
      .forEach((section) => (this.sectionVisibility[section.class] = false));
  }

  getDirtyValues(includeLocalValues = false, localFieldType?: RbdConfigurationSourceField) {
    if (includeLocalValues && !localFieldType) {
      const msg =
        'ProgrammingError: If local values shall be included, a proper localFieldType argument has to be provided, too';
      throw new Error(msg);
    }
    const result = {};

    this.rbdConfigurationService.getWritableOptionFields().forEach((config) => {
      const control = this.form.get('configuration').get(config.name);
      const dirty = control.dirty;

      if (this.initialData && this.initialData[config.name] === control.value) {
        return; // Skip controls with initial data loaded
      }

      if (dirty || (includeLocalValues && control['source'] === localFieldType)) {
        if (control.value === null) {
          result[config.name] = control.value;
        } else if (config.type === RbdConfigurationType.bps) {
          result[config.name] = this.formatterService.toBytes(control.value);
        } else if (config.type === RbdConfigurationType.milliseconds) {
          result[config.name] = this.formatterService.toMilliseconds(control.value);
        } else if (config.type === RbdConfigurationType.iops) {
          result[config.name] = this.formatterService.toIops(control.value);
        } else {
          result[config.name] = control.value;
        }
      }
    });

    return result;
  }

  /**
   * Dynamically create form controls.
   */
  private createConfigurationFormGroup() {
    const configFormGroup = new CdFormGroup({});

    this.rbdConfigurationService.getWritableOptionFields().forEach((c) => {
      let control: FormControl;
      if (
        c.type === RbdConfigurationType.milliseconds ||
        c.type === RbdConfigurationType.iops ||
        c.type === RbdConfigurationType.bps
      ) {
        control = new FormControl(0, Validators.min(0));
      } else {
        throw new Error(
          `Type ${c.type} is unknown, you may need to add it to RbdConfiguration class`
        );
      }
      configFormGroup.addControl(c.name, control);
    });

    return configFormGroup;
  }

  /**
   * Reset the value. The inherited value will be used instead.
   */
  reset(optionName: string) {
    const formControl = this.form.get('configuration').get(optionName);
    if (formControl.disabled) {
      formControl.setValue(formControl['previousValue'] || 0);
      formControl.enable();
      if (!formControl['previousValue']) {
        formControl.markAsPristine();
      }
    } else {
      formControl['previousValue'] = formControl.value;
      formControl.setValue(null);
      formControl.markAsDirty();
      formControl.disable();
    }
  }

  isDisabled(optionName: string) {
    return this.form.get('configuration').get(optionName).disabled;
  }

  toggleSectionVisibility(className) {
    this.sectionVisibility[className] = !this.sectionVisibility[className];
  }
}
<fieldset #cfgFormGroup [formGroup]="form.get('configuration')">
  <legend i18n>RBD Configuration</legend>

  <div *ngFor="let section of rbdConfigurationService.sections">
    <h3 class="page-header">
      <span
        (click)="toggleSectionVisibility(section.class)"
        class="collapsible">{{ section.heading }} <i [ngClass]="{'fa-plus-circle': !sectionVisibility[section.class], 'fa-minus-circle': sectionVisibility[section.class]}" class="fa" aria-hidden="true"></i></span>
    </h3>
    <div class="{{ section.class }}" [hidden]="!sectionVisibility[section.class]">
      <div
        class="form-group"
        *ngFor="let option of section.options"
        [ngClass]="{'has-error': form.showError('configuration.' + option.name, cfgFormGroup)}">
        <label
          class="control-label col-sm-3"
          [for]="option.name">{{ option.displayName }}<cd-helper>{{ option.description }}</cd-helper></label>

        <div class="col-sm-9 {{ section.heading }}">
          <div class="input-group">
            <ng-container [ngSwitch]="option.type">
              <ng-container *ngSwitchCase="configurationType.milliseconds">
                <input
                  [id]="option.name"
                  [name]="option.name"
                  [formControlName]="option.name"
                  type="text"
                  class="form-control"
                  [ngDataReady]="ngDataReady"
                  cdMilliseconds>
              </ng-container>
              <ng-container *ngSwitchCase="configurationType.bps">
                <input
                  [id]="option.name"
                  [name]="option.name"
                  [formControlName]="option.name"
                  type="text"
                  class="form-control"
                  defaultUnit="b"
                  [ngDataReady]="ngDataReady"
                  cdDimlessBinaryPerSecond>
              </ng-container>
              <ng-container *ngSwitchCase="configurationType.iops">
                <input
                  [id]="option.name"
                  [name]="option.name"
                  [formControlName]="option.name"
                  type="text"
                  class="form-control"
                  [ngDataReady]="ngDataReady"
                  cdIops>
              </ng-container>
            </ng-container>
            <span class="input-group-btn">
              <button
                class="btn btn-default"
                type="button"
                data-toggle="button"
                [ngClass]="{'active': isDisabled(option.name)}"
                tooltip="Remove the local configuration value. The parent configuration value will be inherited and used instead."
                containerClass="tooltip-wide"
                [delay]="1000"
                i18n-tooltip
                (click)="reset(option.name)">
                <i class="fa fa-eraser"
                   aria-hidden="true"></i>
              </button>
            </span>
          </div>
          <span
            i18n
            class="help-block"
            *ngIf="form.showError('configuration.' + option.name, cfgFormGroup, 'min')">The mininum value is 0</span>
        </div>
      </div>
    </div>
  </div>

</fieldset>

./rbd-configuration-form.component.scss

.collapsible {
  cursor: pointer;
  user-select: none;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""