Added target and terminal support in Dashboard
[src/xds/xds-agent.git] / webapp / src / app / pages / targets / target-add-modal / target-add-modal.component.ts
1 /**
2 * @license
3 * Copyright (C) 2018 "IoT.bzh"
4 * Author Sebastien Douheret <sebastien@iot.bzh>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 import { Component, ViewEncapsulation, Input, OnInit } from '@angular/core';
20 import { Observable } from 'rxjs/Observable';
21 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
22 import { FormControl, FormGroup, Validators, ValidationErrors, FormBuilder, ValidatorFn, AbstractControl } from '@angular/forms';
23
24 // Import RxJs required methods
25 import 'rxjs/add/operator/map';
26 import 'rxjs/add/operator/filter';
27 import 'rxjs/add/operator/debounceTime';
28
29 import { AlertService, IAlert } from '../../../@core-xds/services/alert.service';
30 import { TargetService, ITarget, TargetType, TargetTypes } from '../../../@core-xds/services/target.service';
31 import { XDSConfigService } from '../../../@core-xds/services/xds-config.service';
32
33
34 @Component({
35   selector: 'xds-target-add-modal',
36   templateUrl: 'target-add-modal.component.html',
37   encapsulation: ViewEncapsulation.None,
38   styles: [`
39     .modal-xxl .modal-lg {
40       width: 90%;
41       max-width:1200px;
42     }
43   `],
44 })
45 export class TargetAddModalComponent implements OnInit {
46   // @Input('server-id') serverID: string;
47   private serverID: string;
48
49   cancelAction = false;
50   userEditedName = false;
51   targetTypes = Object.assign([], TargetTypes);
52
53   addTargetForm: FormGroup;
54   typeCtrl: FormControl;
55   ipCtrl: FormControl;
56
57   constructor(
58     private alert: AlertService,
59     private targetSvr: TargetService,
60     private XdsConfigSvr: XDSConfigService,
61     private fb: FormBuilder,
62     private activeModal: NgbActiveModal,
63   ) {
64     // Define types (first one is special/placeholder)
65     this.targetTypes.unshift({ value: TargetType.UNSET, display: '--Select a type--' });
66
67     // Select first type item (Standard) by default
68     this.typeCtrl = new FormControl(this.targetTypes[1].value, this.validatorTgtType.bind(this));
69     this.ipCtrl = new FormControl('', this.validatorIP.bind(this));
70
71     this.addTargetForm = fb.group({
72       type: this.typeCtrl,
73       ip: this.ipCtrl,
74       name: ['', Validators.nullValidator],
75     });
76   }
77
78   ngOnInit() {
79     // Update server ID
80     this.serverID = this.XdsConfigSvr.getCurServer().id;
81     this.XdsConfigSvr.onCurServer().subscribe(svr => this.serverID = svr.id);
82
83     // Auto create target name
84     this.ipCtrl.valueChanges
85       .debounceTime(100)
86       .filter(n => n)
87       .map(n => {
88         if (this._isIPstart(n)) {
89           return 'Target_' + n;
90         }
91 //        SEB PB
92         return n;
93       })
94       .subscribe(value => {
95         if (value && !this.userEditedName) {
96           this.addTargetForm.patchValue({ name: value });
97         }
98       });
99   }
100
101   closeModal() {
102     this.activeModal.close();
103   }
104
105   onKeyLabel(event: any) {
106     this.userEditedName = (this.addTargetForm.value.label !== '');
107   }
108
109   onChangeLocalTarget(e) {
110   }
111
112   onSubmit() {
113     if (this.cancelAction) {
114       return;
115     }
116
117     const formVal = this.addTargetForm.value;
118
119     this.targetSvr.add({
120       name: formVal['name'],
121       ip: formVal['ip'],
122       type: formVal['type'],
123     }).subscribe(
124       tgt => {
125         this.alert.info('Target ' + tgt.name + ' successfully created.');
126         this.closeModal();
127
128         // Reset Value for the next creation
129         this.addTargetForm.reset();
130         const selectedType = this.targetTypes[0].value;
131         this.addTargetForm.patchValue({ type: selectedType });
132
133       },
134       err => {
135         this.alert.error(err, 60);
136         this.closeModal();
137       },
138     );
139   }
140
141   private validatorTgtType(g: FormGroup): ValidationErrors | null {
142     return (g.value !== TargetType.UNSET) ? null : { validatorTgtType: { valid: false } };
143   }
144
145   private validatorIP(g: FormGroup): ValidationErrors | null {
146     const noValid = <ValidationErrors>{ validatorProjPath: { valid: false } };
147
148     if (g.value === '') {
149       return noValid;
150     }
151
152     if (this._isIPstart(g.value) && !this._isIPv4(g.value)) {
153       return noValid;
154     }
155
156     // Else accept any text / hostname
157     return null;
158   }
159
160   private _isIPstart(str) {
161     return /^(\d+)\./.test(str);
162   }
163
164   private _isIPv4(str) {
165     const ipv4Maybe = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
166     if (!ipv4Maybe.test(str)) {
167       return false;
168     }
169     const parts = str.split('.').sort(function (a, b) {
170       return a - b;
171     });
172     return (parts[3] <= 255);
173   }
174 }