import { RbdFormComponent } from './ceph/block/rbd-form/rbd-form.component';
import { RbdImagesComponent } from './ceph/block/rbd-images/rbd-images.component';
import { CephfsListComponent } from './ceph/cephfs/cephfs-list/cephfs-list.component';
+import { ConfigurationFormComponent } from './ceph/cluster/configuration/configuration-form/configuration-form.component';
import { ConfigurationComponent } from './ceph/cluster/configuration/configuration.component';
import { HostsComponent } from './ceph/cluster/hosts/hosts.component';
import { MonitorComponent } from './ceph/cluster/monitor/monitor.component';
},
{
path: 'configuration',
- component: ConfigurationComponent,
- canActivate: [AuthGuardService],
- data: { breadcrumbs: 'Cluster/Configuration Documentation' }
+ data: { breadcrumbs: 'Cluster/Configuration Documentation' },
+ children: [
+ { path: '', component: ConfigurationComponent },
+ {
+ path: 'edit/:name',
+ component: ConfigurationFormComponent,
+ data: { breadcrumbs: 'Edit' }
+ }
+ ]
},
{
path: 'perf_counters/:type/:id',
import { SharedModule } from '../../shared/shared.module';
import { PerformanceCounterModule } from '../performance-counter/performance-counter.module';
import { ConfigurationDetailsComponent } from './configuration/configuration-details/configuration-details.component';
+import { ConfigurationFormComponent } from './configuration/configuration-form/configuration-form.component';
import { ConfigurationComponent } from './configuration/configuration.component';
import { HostDetailsComponent } from './hosts/host-details/host-details.component';
import { HostsComponent } from './hosts/hosts.component';
OsdScrubModalComponent,
OsdFlagsModalComponent,
HostDetailsComponent,
- ConfigurationDetailsComponent
+ ConfigurationDetailsComponent,
+ ConfigurationFormComponent
]
})
export class ClusterModule {}
--- /dev/null
+<div class="col-sm-12 col-lg-6">
+ <form name="configForm"
+ class="form-horizontal"
+ #formDir="ngForm"
+ [formGroup]="configForm"
+ novalidate>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">
+ <ng-container i18>Edit</ng-container> {{ configForm.getValue('name') }}
+ </h3>
+ </div>
+ <div class="panel-body">
+
+ <!-- Name -->
+ <div class="form-group">
+ <label i18n
+ class="control-label col-sm-3">Name
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="name"
+ formControlName="name"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Description -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('desc')">
+ <label i18n
+ class="control-label col-sm-3">Description
+ </label>
+ <div class="col-sm-9">
+ <textarea class="form-control"
+ id="desc"
+ formControlName="desc"
+ readonly>
+ </textarea>
+ </div>
+ </div>
+
+ <!-- Long description -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('long_desc')">
+ <label i18n
+ class="control-label col-sm-3">Long description
+ </label>
+ <div class="col-sm-9">
+ <textarea class="form-control"
+ id="long_desc"
+ formControlName="long_desc"
+ readonly>
+ </textarea>
+ </div>
+ </div>
+
+ <!-- Default -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('default') !== ''">
+ <label i18n
+ class="control-label col-sm-3">Default
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="default"
+ formControlName="default"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Daemon default -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('daemon_default') !== ''">
+ <label i18n
+ class="control-label col-sm-3">Daemon default
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="daemon_default"
+ formControlName="daemon_default"
+ readonly>
+ </div>
+ </div>
+
+ <!-- Services -->
+ <div class="form-group"
+ *ngIf="configForm.getValue('services').length > 0">
+ <label i18n
+ class="control-label col-sm-3">Services
+ </label>
+ <div class="col-sm-9">
+ <span *ngFor="let service of configForm.getValue('services')"
+ class="form-component-badge">
+ <span class="badge badge-pill badge-primary">{{ service }}</span>
+ </span>
+ </div>
+ </div>
+
+ <!-- Values -->
+ <div class="col-sm-12">
+ <h2 i18n
+ class="page-header">Values</h2>
+ <div class="row" *ngFor="let section of availSections">
+ <div class="form-group" *ngIf="type === 'bool'">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="checkbox checkbox-primary">
+ <input [id]="section"
+ type="checkbox"
+ [formControlName]="section">
+ <label [for]="section"
+ i18n>{{ section }}
+ </label>
+ </div>
+ </div>
+ </div>
+ <div class="form-group"
+ [ngClass]="{'has-error': configForm.showError(section, formDir)}"
+ *ngIf="type !== 'bool'">
+ <label class="control-label col-sm-3"
+ [for]="section"
+ i18n>{{ section }}
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ [type]="inputType"
+ [id]="section"
+ [placeholder]="humanReadableType"
+ [formControlName]="section"
+ [step]="getStep(type, this.configForm.getValue(section))">
+ <span class="help-block"
+ *ngIf="configForm.showError(section, formDir, 'pattern')"
+ i18n>
+ {{ patternHelpText }}
+ </span>
+ <span class="help-block"
+ *ngIf="configForm.showError(section, formDir, 'max')"
+ i18n>
+ The entered value is too high! It must not be greater than {{ maxValue }}.
+ </span>
+ <span class="help-block"
+ *ngIf="configForm.showError(section, formDir, 'min')"
+ i18n>
+ The entered value is too low! It must not be lower than {{ minValue }}.
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- Footer -->
+ <div class="panel-footer">
+ <div class="button-group text-right">
+ <button type="button"
+ class="btn btn-sm btn-default"
+ routerLink="/configuration"
+ i18n>
+ Back
+ </button>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
--- /dev/null
+.form-component-badge {
+ height: 34px;
+ display: block;
+
+ span {
+ margin-top: 7px;
+ }
+}
--- /dev/null
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed } from '../../../../../testing/unit-test-helper';
+import { SharedModule } from '../../../../shared/shared.module';
+import { ConfigurationFormComponent } from './configuration-form.component';
+import { ConfigFormModel } from './configuration-form.model';
+
+describe('ConfigurationFormComponent', () => {
+ let component: ConfigurationFormComponent;
+ let fixture: ComponentFixture<ConfigurationFormComponent>;
+ let activatedRoute: ActivatedRoute;
+
+ configureTestBed({
+ imports: [HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule, SharedModule],
+ declarations: [ConfigurationFormComponent],
+ providers: [
+ {
+ provide: ActivatedRoute
+ }
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ConfigurationFormComponent);
+ component = fixture.componentInstance;
+ activatedRoute = TestBed.get(ActivatedRoute);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ describe('getType', () => {
+ it('should return uint64_t type', () => {
+ const ret = component.getType('uint64_t');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('uint64_t');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Positive integer value');
+ expect(ret.defaultMin).toBe(0);
+ expect(ret.patternHelpText).toBe('The entered value needs to be a positive number.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(false);
+ });
+
+ it('should return int64_t type', () => {
+ const ret = component.getType('int64_t');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('int64_t');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Integer value');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe('The entered value needs to be a number.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(true);
+ });
+
+ it('should return size_t type', () => {
+ const ret = component.getType('size_t');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('size_t');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Positive integer value (size)');
+ expect(ret.defaultMin).toBe(0);
+ expect(ret.patternHelpText).toBe('The entered value needs to be a positive number.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(false);
+ });
+
+ it('should return secs type', () => {
+ const ret = component.getType('secs');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('secs');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Positive integer value (secs)');
+ expect(ret.defaultMin).toBe(1);
+ expect(ret.patternHelpText).toBe('The entered value needs to be a positive number.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(false);
+ });
+
+ it('should return double type', () => {
+ const ret = component.getType('double');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('double');
+ expect(ret.inputType).toBe('number');
+ expect(ret.humanReadable).toBe('Decimal value');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe('The entered value needs to be a number or decimal.');
+ expect(ret.isNumberType).toBe(true);
+ expect(ret.allowsNegative).toBe(true);
+ });
+
+ it('should return std::string type', () => {
+ const ret = component.getType('std::string');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('std::string');
+ expect(ret.inputType).toBe('text');
+ expect(ret.humanReadable).toBe('Text');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBeUndefined();
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should return entity_addr_t type', () => {
+ const ret = component.getType('entity_addr_t');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('entity_addr_t');
+ expect(ret.inputType).toBe('text');
+ expect(ret.humanReadable).toBe('IPv4 or IPv6 address');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe('The entered value needs to be a valid IP address.');
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should return uuid_d type', () => {
+ const ret = component.getType('uuid_d');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('uuid_d');
+ expect(ret.inputType).toBe('text');
+ expect(ret.humanReadable).toBe('UUID');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBe(
+ 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8'
+ );
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should return bool type', () => {
+ const ret = component.getType('bool');
+ expect(ret).toBeTruthy();
+ expect(ret.name).toBe('bool');
+ expect(ret.inputType).toBe('checkbox');
+ expect(ret.humanReadable).toBe('Boolean value');
+ expect(ret.defaultMin).toBeUndefined();
+ expect(ret.patternHelpText).toBeUndefined();
+ expect(ret.isNumberType).toBe(false);
+ expect(ret.allowsNegative).toBeUndefined();
+ });
+
+ it('should throw an error for unknown type', () => {
+ expect(() =>
+ component.getType('unknown').toThrowError('Found unknown type "unknown" for config option.')
+ );
+ });
+ });
+
+ describe('getValidators', () => {
+ it('should return a validator for types double, entity_addr_t and uuid_d', () => {
+ const types = ['double', 'entity_addr_t', 'uuid_d'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(1);
+ });
+ });
+
+ it('should not return a validator for types std::string and bool', () => {
+ const types = ['std::string', 'bool'];
+
+ types.forEach((valType) => {
+ const configOption = new ConfigFormModel();
+ configOption.type = valType;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeUndefined();
+ });
+ });
+
+ it('should return a pattern and a min validator', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'int64_t';
+ configOption.min = 2;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(2);
+ expect(component.minValue).toBe(2);
+ expect(component.maxValue).toBeUndefined();
+ });
+
+ it('should return a pattern and a max validator', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'int64_t';
+ configOption.max = 5;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(2);
+ expect(component.minValue).toBeUndefined();
+ expect(component.maxValue).toBe(5);
+ });
+
+ it('should return multiple validators', () => {
+ const configOption = new ConfigFormModel();
+ configOption.type = 'double';
+ configOption.max = 5.2;
+ configOption.min = 1.5;
+
+ const ret = component.getValidators(configOption);
+ expect(ret).toBeTruthy();
+ expect(ret.length).toBe(3);
+ expect(component.minValue).toBe(1.5);
+ expect(component.maxValue).toBe(5.2);
+ });
+ });
+
+ describe('getStep', () => {
+ it('should return the correct step for type uint64_t and value 0', () => {
+ const ret = component.getStep('uint64_t', 0);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type int64_t and value 1', () => {
+ const ret = component.getStep('int64_t', 1);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type int64_t and value null', () => {
+ const ret = component.getStep('int64_t', null);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type size_t and value 2', () => {
+ const ret = component.getStep('size_t', 2);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type secs and value 3', () => {
+ const ret = component.getStep('secs', 3);
+ expect(ret).toBe(1);
+ });
+
+ it('should return the correct step for type double and value 1', () => {
+ const ret = component.getStep('double', 1);
+ expect(ret).toBe(0.1);
+ });
+
+ it('should return the correct step for type double and value 0.1', () => {
+ const ret = component.getStep('double', 0.1);
+ expect(ret).toBe(0.1);
+ });
+
+ it('should return the correct step for type double and value 0.02', () => {
+ const ret = component.getStep('double', 0.02);
+ expect(ret).toBe(0.01);
+ });
+
+ it('should return the correct step for type double and value 0.003', () => {
+ const ret = component.getStep('double', 0.003);
+ expect(ret).toBe(0.001);
+ });
+
+ it('should return the correct step for type double and value null', () => {
+ const ret = component.getStep('double', null);
+ expect(ret).toBe(0.1);
+ });
+
+ it('should return undefined for unknown type', () => {
+ const ret = component.getStep('unknown', 1);
+ expect(ret).toBeUndefined();
+ });
+ });
+});
--- /dev/null
+import { Component, OnInit } from '@angular/core';
+import { FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { ConfigurationService } from '../../../../shared/api/configuration.service';
+import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
+import { CdValidators } from '../../../../shared/forms/cd-validators';
+import { ConfigFormModel } from './configuration-form.model';
+
+@Component({
+ selector: 'cd-configuration-form',
+ templateUrl: './configuration-form.component.html',
+ styleUrls: ['./configuration-form.component.scss']
+})
+export class ConfigurationFormComponent implements OnInit {
+ configForm: CdFormGroup;
+ response: ConfigFormModel;
+ type: string;
+ inputType: string;
+ humanReadableType: string;
+ minValue: number;
+ maxValue: number;
+ patternHelpText: string;
+ availSections = ['global', 'mon', 'mgr', 'osd', 'mds', 'client'];
+
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ private configService: ConfigurationService
+ ) {
+ this.createForm();
+ }
+
+ createForm() {
+ const formControls = {
+ name: new FormControl({ value: null }),
+ desc: new FormControl({ value: null }),
+ long_desc: new FormControl({ value: null }),
+ values: new FormGroup({}),
+ default: new FormControl({ value: null }),
+ daemon_default: new FormControl({ value: null }),
+ services: new FormControl([])
+ };
+
+ this.availSections.forEach((section) => {
+ formControls.values.controls[section] = new FormControl(null);
+ });
+
+ this.configForm = new CdFormGroup(formControls);
+ this.configForm._filterValue = (value) => {
+ return value;
+ };
+ }
+
+ ngOnInit() {
+ this.route.params.subscribe((params: { name: string }) => {
+ const configName = params.name;
+ this.configService.get(configName).subscribe((resp: ConfigFormModel) => {
+ this.setResponse(resp);
+ });
+ });
+ }
+
+ getType(type: string): any {
+ const knownTypes = [
+ {
+ name: 'uint64_t',
+ inputType: 'number',
+ humanReadable: 'Positive integer value',
+ defaultMin: 0,
+ patternHelpText: 'The entered value needs to be a positive number.',
+ isNumberType: true,
+ allowsNegative: false
+ },
+ {
+ name: 'int64_t',
+ inputType: 'number',
+ humanReadable: 'Integer value',
+ patternHelpText: 'The entered value needs to be a number.',
+ isNumberType: true,
+ allowsNegative: true
+ },
+ {
+ name: 'size_t',
+ inputType: 'number',
+ humanReadable: 'Positive integer value (size)',
+ defaultMin: 0,
+ patternHelpText: 'The entered value needs to be a positive number.',
+ isNumberType: true,
+ allowsNegative: false
+ },
+ {
+ name: 'secs',
+ inputType: 'number',
+ humanReadable: 'Positive integer value (secs)',
+ defaultMin: 1,
+ patternHelpText: 'The entered value needs to be a positive number.',
+ isNumberType: true,
+ allowsNegative: false
+ },
+ {
+ name: 'double',
+ inputType: 'number',
+ humanReadable: 'Decimal value',
+ patternHelpText: 'The entered value needs to be a number or decimal.',
+ isNumberType: true,
+ allowsNegative: true
+ },
+ { name: 'std::string', inputType: 'text', humanReadable: 'Text', isNumberType: false },
+ {
+ name: 'entity_addr_t',
+ inputType: 'text',
+ humanReadable: 'IPv4 or IPv6 address',
+ patternHelpText: 'The entered value needs to be a valid IP address.',
+ isNumberType: false
+ },
+ {
+ name: 'uuid_d',
+ inputType: 'text',
+ humanReadable: 'UUID',
+ patternHelpText:
+ 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8',
+ isNumberType: false
+ },
+ { name: 'bool', inputType: 'checkbox', humanReadable: 'Boolean value', isNumberType: false }
+ ];
+
+ let currentType = null;
+
+ knownTypes.forEach((knownType) => {
+ if (knownType.name === type) {
+ currentType = knownType;
+ }
+ });
+
+ if (currentType !== null) {
+ return currentType;
+ }
+
+ throw new Error('Found unknown type "' + type + '" for config option.');
+ }
+
+ getValidators(configOption: any): ValidatorFn[] {
+ const typeParams = this.getType(configOption.type);
+ this.patternHelpText = typeParams.patternHelpText;
+
+ if (typeParams.isNumberType) {
+ const validators = [];
+
+ if (configOption.max && configOption.max !== '') {
+ this.maxValue = configOption.max;
+ validators.push(Validators.max(configOption.max));
+ }
+
+ if ('min' in configOption && configOption.min !== '') {
+ this.minValue = configOption.min;
+ validators.push(Validators.min(configOption.min));
+ } else if ('defaultMin' in typeParams) {
+ this.minValue = typeParams.defaultMin;
+ validators.push(Validators.min(typeParams.defaultMin));
+ }
+
+ if (configOption.type === 'double') {
+ validators.push(CdValidators.decimalNumber());
+ } else {
+ validators.push(CdValidators.number(typeParams.allowsNegative));
+ }
+
+ return validators;
+ } else if (configOption.type === 'entity_addr_t') {
+ return [CdValidators.ip()];
+ } else if (configOption.type === 'uuid_d') {
+ return [CdValidators.uuid()];
+ }
+ }
+
+ getStep(type: string, value: number): number | undefined {
+ const numberTypes = ['uint64_t', 'int64_t', 'size_t', 'secs'];
+
+ if (numberTypes.includes(type)) {
+ return 1;
+ }
+
+ if (type === 'double') {
+ if (value !== null) {
+ const stringVal = value.toString();
+ if (stringVal.indexOf('.') !== -1) {
+ // Value type double and contains decimal characters
+ const decimal = value.toString().split('.');
+ return Math.pow(10, -decimal[1].length);
+ }
+ }
+
+ return 0.1;
+ }
+
+ return undefined;
+ }
+
+ setResponse(response: ConfigFormModel) {
+ this.response = response;
+ const validators = this.getValidators(response);
+
+ this.configForm.get('name').setValue(response.name);
+ this.configForm.get('desc').setValue(response.desc);
+ this.configForm.get('long_desc').setValue(response.long_desc);
+ this.configForm.get('default').setValue(response.default);
+ this.configForm.get('daemon_default').setValue(response.daemon_default);
+ this.configForm.get('services').setValue(response.services);
+
+ if (this.response.value) {
+ this.response.value.forEach((value) => {
+ // Check value type. If it's a boolean value we need to convert it because otherwise we
+ // would use the string representation. That would cause issues for e.g. checkboxes.
+ let sectionValue = null;
+ if (value.value === 'true') {
+ sectionValue = true;
+ } else if (value.value === 'false') {
+ sectionValue = false;
+ } else {
+ sectionValue = value.value;
+ }
+ this.configForm
+ .get('values')
+ .get(value.section)
+ .setValue(sectionValue);
+ });
+ }
+
+ this.availSections.forEach((section) => {
+ this.configForm
+ .get('values')
+ .get(section)
+ .setValidators(validators);
+ });
+
+ const currentType = this.getType(response.type);
+ this.type = currentType.name;
+ this.inputType = currentType.inputType;
+ this.humanReadableType = currentType.humanReadable;
+ }
+}
--- /dev/null
+export class ConfigFormModel {
+ name: string;
+ desc: string;
+ long_desc: string;
+ type: string;
+ value: Array<any>;
+ default: any;
+ daemon_default: any;
+ min: any;
+ max: any;
+ services: Array<string>;
+}
[columns]="columns"
selectionType="single"
(updateSelection)="updateSelection($event)">
- <div class="table-actions form-inline">
+ <cd-table-actions class="table-actions"
+ [permission]="permission"
+ [selection]="selection"
+ [tableActions]="tableActions">
+ </cd-table-actions>
+ <div class="table-filters">
<div class="form-group filter"
*ngFor="let filter of filters">
<label>{{ filter.label }}: </label>
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { ConfigurationService } from '../../../shared/api/configuration.service';
+import { CdTableAction } from '../../../shared/models/cd-table-action';
import { CdTableColumn } from '../../../shared/models/cd-table-column';
import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
import { CdTableSelection } from '../../../shared/models/cd-table-selection';
+import { Permission } from '../../../shared/models/permissions';
+import { AuthStorageService } from '../../../shared/services/auth-storage.service';
@Component({
selector: 'cd-configuration',
styleUrls: ['./configuration.component.scss']
})
export class ConfigurationComponent implements OnInit {
+ permission: Permission;
+ tableActions: CdTableAction[];
data = [];
columns: CdTableColumn[];
selection = new CdTableSelection();
@ViewChild('confFlagTpl')
public confFlagTpl: TemplateRef<any>;
- constructor(private configurationService: ConfigurationService) {}
+ constructor(
+ private authStorageService: AuthStorageService,
+ private configurationService: ConfigurationService
+ ) {
+ this.permission = this.authStorageService.getPermissions().configOpt;
+ const getConfigOptUri = () =>
+ this.selection.first() && `${encodeURI(this.selection.first().name)}`;
+ const editAction: CdTableAction = {
+ permission: 'update',
+ icon: 'fa-pencil',
+ routerLink: () => `/configuration/edit/${getConfigOptUri()}`,
+ name: 'Edit'
+ };
+ this.tableActions = [editAction];
+ }
ngOnInit() {
this.columns = [
getConfigData() {
return this.http.get('api/cluster_conf/');
}
+
+ get(configOption) {
+ return this.http.get(`api/cluster_conf/${configOption}`);
+ }
}