1 import { Component, OnInit } from '@angular/core';
2 import { FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
3 import { ActivatedRoute, Router } from '@angular/router';
5 import * as _ from 'lodash';
7 import { ConfigurationService } from '../../../../shared/api/configuration.service';
8 import { NotificationType } from '../../../../shared/enum/notification-type.enum';
9 import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
10 import { CdValidators } from '../../../../shared/forms/cd-validators';
11 import { NotificationService } from '../../../../shared/services/notification.service';
12 import { ConfigFormCreateRequestModel } from './configuration-form-create-request.model';
13 import { ConfigFormModel } from './configuration-form.model';
16 selector: 'cd-configuration-form',
17 templateUrl: './configuration-form.component.html',
18 styleUrls: ['./configuration-form.component.scss']
20 export class ConfigurationFormComponent implements OnInit {
21 configForm: CdFormGroup;
22 response: ConfigFormModel;
25 humanReadableType: string;
28 patternHelpText: string;
29 availSections = ['global', 'mon', 'mgr', 'osd', 'mds', 'client'];
32 private route: ActivatedRoute,
33 private router: Router,
34 private configService: ConfigurationService,
35 private notificationService: NotificationService
41 const formControls = {
42 name: new FormControl({ value: null }),
43 desc: new FormControl({ value: null }),
44 long_desc: new FormControl({ value: null }),
45 values: new FormGroup({}),
46 default: new FormControl({ value: null }),
47 daemon_default: new FormControl({ value: null }),
48 services: new FormControl([])
51 this.availSections.forEach((section) => {
52 formControls.values.addControl(section, new FormControl(null));
55 this.configForm = new CdFormGroup(formControls);
56 this.configForm._filterValue = (value) => {
62 this.route.params.subscribe((params: { name: string }) => {
63 const configName = params.name;
64 this.configService.get(configName).subscribe((resp: ConfigFormModel) => {
65 this.setResponse(resp);
70 getType(type: string): any {
75 humanReadable: 'Positive integer value',
77 patternHelpText: 'The entered value needs to be a positive number.',
84 humanReadable: 'Integer value',
85 patternHelpText: 'The entered value needs to be a number.',
92 humanReadable: 'Positive integer value (size)',
94 patternHelpText: 'The entered value needs to be a positive number.',
101 humanReadable: 'Positive integer value (secs)',
103 patternHelpText: 'The entered value needs to be a positive number.',
105 allowsNegative: false
110 humanReadable: 'Decimal value',
111 patternHelpText: 'The entered value needs to be a number or decimal.',
115 { name: 'std::string', inputType: 'text', humanReadable: 'Text', isNumberType: false },
117 name: 'entity_addr_t',
119 humanReadable: 'IPv4 or IPv6 address',
120 patternHelpText: 'The entered value needs to be a valid IP address.',
126 humanReadable: 'UUID',
128 'The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8',
131 { name: 'bool', inputType: 'checkbox', humanReadable: 'Boolean value', isNumberType: false }
134 let currentType = null;
136 knownTypes.forEach((knownType) => {
137 if (knownType.name === type) {
138 currentType = knownType;
142 if (currentType !== null) {
146 throw new Error('Found unknown type "' + type + '" for config option.');
149 getValidators(configOption: any): ValidatorFn[] {
150 const typeParams = this.getType(configOption.type);
151 this.patternHelpText = typeParams.patternHelpText;
153 if (typeParams.isNumberType) {
154 const validators = [];
156 if (configOption.max && configOption.max !== '') {
157 this.maxValue = configOption.max;
158 validators.push(Validators.max(configOption.max));
161 if ('min' in configOption && configOption.min !== '') {
162 this.minValue = configOption.min;
163 validators.push(Validators.min(configOption.min));
164 } else if ('defaultMin' in typeParams) {
165 this.minValue = typeParams.defaultMin;
166 validators.push(Validators.min(typeParams.defaultMin));
169 if (configOption.type === 'double') {
170 validators.push(CdValidators.decimalNumber());
172 validators.push(CdValidators.number(typeParams.allowsNegative));
176 } else if (configOption.type === 'entity_addr_t') {
177 return [CdValidators.ip()];
178 } else if (configOption.type === 'uuid_d') {
179 return [CdValidators.uuid()];
183 getStep(type: string, value: number): number | undefined {
184 const numberTypes = ['uint64_t', 'int64_t', 'size_t', 'secs'];
186 if (numberTypes.includes(type)) {
190 if (type === 'double') {
191 if (value !== null) {
192 const stringVal = value.toString();
193 if (stringVal.indexOf('.') !== -1) {
194 // Value type double and contains decimal characters
195 const decimal = value.toString().split('.');
196 return Math.pow(10, -decimal[1].length);
206 setResponse(response: ConfigFormModel) {
207 this.response = response;
208 const validators = this.getValidators(response);
210 this.configForm.get('name').setValue(response.name);
211 this.configForm.get('desc').setValue(response.desc);
212 this.configForm.get('long_desc').setValue(response.long_desc);
213 this.configForm.get('default').setValue(response.default);
214 this.configForm.get('daemon_default').setValue(response.daemon_default);
215 this.configForm.get('services').setValue(response.services);
217 if (this.response.value) {
218 this.response.value.forEach((value) => {
219 // Check value type. If it's a boolean value we need to convert it because otherwise we
220 // would use the string representation. That would cause issues for e.g. checkboxes.
221 let sectionValue = null;
222 if (value.value === 'true') {
224 } else if (value.value === 'false') {
225 sectionValue = false;
227 sectionValue = value.value;
232 .setValue(sectionValue);
236 this.availSections.forEach((section) => {
240 .setValidators(validators);
243 const currentType = this.getType(response.type);
244 this.type = currentType.name;
245 this.inputType = currentType.inputType;
246 this.humanReadableType = currentType.humanReadable;
249 createRequest(): ConfigFormCreateRequestModel | null {
252 this.availSections.forEach((section) => {
253 const sectionValue = this.configForm.getValue(section);
255 values.push({ section: section, value: sectionValue });
259 if (!_.isEqual(this.response.value, values)) {
260 const request = new ConfigFormCreateRequestModel();
261 request.name = this.configForm.getValue('name');
262 request.value = values;
270 const request = this.createRequest();
273 this.configService.create(request).subscribe(
275 this.notificationService.show(
276 NotificationType.success,
277 'Config option ' + request.name + ' has been updated.',
278 'Update config option'
280 this.router.navigate(['/configuration']);
283 this.configForm.setErrors({ cdSubmitButton: true });
288 this.router.navigate(['/configuration']);