Fix Bug 2291: No option to update VIM Account in NG-UI
[osm/NG-UI.git] / src / app / vim-accounts / new-vimaccount / NewVimaccountComponent.ts
index 0c2b3d6..724bef2 100644 (file)
 /**
  * @file Vim Account Component.
  */
+import { isNullOrUndefined } from 'util';
 import { HttpHeaders } from '@angular/common/http';
 import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
-import { FormBuilder, FormGroup, Validators } from '@angular/forms';
-import { Router } from '@angular/router';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { ActivatedRoute, Router } from '@angular/router';
+import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
 import { TranslateService } from '@ngx-translate/core';
 import { NotifierService } from 'angular-notifier';
 import 'codemirror/addon/dialog/dialog';
@@ -40,17 +42,15 @@ import 'codemirror/mode/javascript/javascript';
 import 'codemirror/mode/markdown/markdown';
 import 'codemirror/mode/yaml/yaml';
 import {
-  APIURLHEADER, ERRORDATA, TYPEAWS, TYPEAZURE, TYPEOPENSTACK, TYPEOPENVIMNEBULA, TYPEOTERS,
+  APIURLHEADER, CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA, TYPEAWS, TYPEAZURE, TYPEOPENSTACK, TYPEOPENVIMNEBULA, TYPEOTERS,
   TYPESECTION, TYPEVMWARE, VIM_TYPES
 } from 'CommonModel';
 import { environment } from 'environment';
 import * as jsyaml from 'js-yaml';
 import { RestService } from 'RestService';
 import { SharedService } from 'SharedService';
-import { isNullOrUndefined } from 'util';
-import { FEATURES, VIMLOCATION, VIMLOCATIONDATA } from 'VimAccountModel';
-import { VimAccountDetails, VIMData } from 'VimAccountModel';
-
+import { VimAccountDetails } from 'VimAccountModel';
+import { WarningComponent } from 'WarningComponent';
 /**
  * Creating component
  * @Component takes NewVimaccountComponent.html as template url
@@ -74,29 +74,20 @@ export class NewVimaccountComponent implements OnInit {
   /** Supported Vim type for the dropdown */
   public selectedVimType: string;
 
-  /** Supported true and false value for the dropdown */
-  public boolValue: {}[];
-
   /** Form submission Add */
   public submitted: boolean = false;
 
   /** Showing more details of collapase */
   public isCollapsed: boolean = false;
 
-  /** Vim location values @public */
-  public getVIMLocation: VIMLOCATIONDATA[] = [];
-
   /** Check the Projects loading results @public */
   public isLocationLoadingResults: boolean = false;
 
   /** Give the message for the loading @public */
   public message: string = 'PLEASEWAIT';
 
-  /** set the longitude value of the selected place @public */
-  public setLong: number;
-
-  /** set the latitude value of the selected place @public */
-  public setLat: number;
+  /** Set the check value  @public */
+  public check: boolean = false;
 
   /** Handle the formate Change @public */
   public defaults: {} = {
@@ -111,9 +102,10 @@ export class NewVimaccountComponent implements OnInit {
 
   /** options @public */
   public options: {} = {
+    // eslint-disable-next-line no-invalid-this
     mode: this.modeDefault,
     showCursorWhenSelecting: true,
-    autofocus: true,
+    autofocus: false,
     autoRefresh: true,
     lineNumbers: true,
     lineWrapping: true,
@@ -128,8 +120,8 @@ export class NewVimaccountComponent implements OnInit {
   /** Data @public */
   public data: string = '';
 
-  /** Controls the File Type List form @public */
-  public fileTypes: { value: string; viewValue: string; }[] = [];
+  /** contains vim ID @public */
+  public vimID: string;
 
   /** Element ref for fileInput @public */
   @ViewChild('fileInput', { static: true }) public fileInput: ElementRef;
@@ -140,6 +132,45 @@ export class NewVimaccountComponent implements OnInit {
   /** Contains all methods related to shared @private */
   public sharedService: SharedService;
 
+  /** Check key for the Edit form @public */
+  public checkFormKeys: string[] =
+    [
+      'name',
+      'vim_type',
+      'vim_tenant_name',
+      'description',
+      'vim_url',
+      'schema_type',
+      'vim_user',
+      'vim_password',
+      'locationName',
+      'latitude',
+      'longitude',
+      'config'
+    ];
+
+  /** Contains config details in edit @public */
+  public config: {};
+
+  /** Contains latitude value @public  */
+  public latitude: string;
+
+  /** Contains longitude value @public  */
+  public longitude: string;
+
+  /** Contains location value @public */
+  public locationName: string;
+
+  /** Contains VIMAccount Details @private */
+  private details: VimAccountDetails;
+
+  /** Contains config with location @private */
+  private configLocation: string;
+
+  /** Check for config length @private */
+  // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+  private configLength: number = 3;
+
   /** Instance of the rest service @private */
   private restService: RestService;
 
@@ -158,11 +189,11 @@ export class NewVimaccountComponent implements OnInit {
   /** Contains tranlsate instance @private */
   private translateService: TranslateService;
 
-  /** VIM Details @private */
-  private vimDetail: VimAccountDetails[];
+  /** Holds teh instance of AuthService class of type AuthService @private */
+  private activatedRoute: ActivatedRoute;
 
-  /** convenience getter for easy access to form fields */
-  get f(): FormGroup['controls'] { return this.vimNewAccountForm.controls; }
+  /** Instance of the modal service @private */
+  private modalService: NgbModal;
 
   constructor(injector: Injector) {
     this.injector = injector;
@@ -172,8 +203,32 @@ export class NewVimaccountComponent implements OnInit {
     this.notifierService = this.injector.get(NotifierService);
     this.translateService = this.injector.get(TranslateService);
     this.sharedService = this.injector.get(SharedService);
+    this.activatedRoute = this.injector.get(ActivatedRoute);
+    this.modalService = this.injector.get(NgbModal);
+  }
+
+  /** convenience getter for easy access to form fields */
+  get f(): FormGroup['controls'] { return this.vimNewAccountForm.controls; }
+
+  /**
+   * Lifecyle Hooks the trigger before component is instantiate
+   */
+  public ngOnInit(): void {
+    this.vimID = this.activatedRoute.snapshot.paramMap.get('id');
+    this.vimType = VIM_TYPES;
+    this.headers = new HttpHeaders({
+      Accept: 'application/json',
+      'Content-Type': 'application/json',
+      'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+    });
+    this.initializeForm();
+    if (!isNullOrUndefined(this.vimID)) {
+      this.getVIMDetails(this.vimID);
+    }
+  }
 
-    /** Initializing Form Action */
+  /** VIM Initialize Forms @public */
+  public initializeForm(): void {
     this.vimNewAccountForm = this.formBuilder.group({
       name: [null, Validators.required],
       vim_type: [null, Validators.required],
@@ -183,6 +238,9 @@ export class NewVimaccountComponent implements OnInit {
       schema_type: [''],
       vim_user: [null, Validators.required],
       vim_password: [null, Validators.required],
+      locationName: [''],
+      latitude: ['', Validators.pattern(this.sharedService.REGX_LAT_PATTERN)],
+      longitude: ['', Validators.pattern(this.sharedService.REGX_LONG_PATTERN)],
       config: this.paramsBuilder()
     });
   }
@@ -194,68 +252,137 @@ export class NewVimaccountComponent implements OnInit {
     });
   }
 
-  /**
-   * Lifecyle Hooks the trigger before component is instantiate
-   */
-  public ngOnInit(): void {
-    this.fileTypes = [{ value: 'text/x-yaml', viewValue: 'yaml' }];
-    this.vimType = VIM_TYPES;
-    this.boolValue = [
-      { id: '', name: 'None' },
-      { id: true, name: 'True' },
-      { id: false, name: 'False' }
-    ];
-    this.headers = new HttpHeaders({
-      Accept: 'application/json',
-      'Content-Type': 'application/json',
-      'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+  /** Fetching the vim details from get api @protected */
+  private getVIMDetails(id: string): void {
+    this.isLocationLoadingResults = true;
+    this.restService.getResource(environment.VIMACCOUNTS_URL + '/' + id).subscribe((vimAccountsData: VimAccountDetails) => {
+      this.details = vimAccountsData;
+      if (!isNullOrUndefined(this.details.config.location)) {
+        this.configLocation = this.details.config.location;
+        if (this.configLocation.indexOf(',') !== -1) {
+          this.locationName = this.configLocation.split(',')[0];
+          this.latitude = this.configLocation.split(',')[1];
+          this.longitude = this.configLocation.split(',')[2];
+        }
+      }
+      delete this.details.config.location;
+      this.getFormControl('schema_type').disable();
+      this.getFormControl('vim_url').disable();
+      this.getFormControl('vim_type').disable();
+      this.config = { ...this.details.config };
+      this.details.vim_password = '';
+      this.setEditValue(this.details, this.checkFormKeys);
+      this.isLocationLoadingResults = false;
+    }, (error: ERRORDATA) => {
+      this.restService.handleError(error, 'get');
+      this.isLocationLoadingResults = false;
+    });
+  }
+
+  /** Set the value for the Edit Section @public */
+  public setEditValue(formValues: VimAccountDetails, checkKey: string[]): void {
+    Object.keys(formValues).forEach((name: string): void => {
+      if (checkKey.includes(name)) {
+        if (name === 'config') {
+          this.loadConfig();
+          this.getFormControl('locationName').patchValue(this.locationName);
+          this.getFormControl('latitude').patchValue(this.latitude);
+          this.getFormControl('longitude').patchValue(this.longitude);
+        }
+        else {
+          // eslint-disable-next-line security/detect-object-injection
+          this.getFormControl(name).setValue(formValues[name], { onlySelf: true });
+          this.getFormControl(name).updateValueAndValidity();
+        }
+      }
     });
-    this.getVIMDetails();
   }
 
   /** On modal submit newVimAccountSubmit will called @public */
   public newVimAccountSubmit(): void {
     this.submitted = true;
+
     if (!this.vimNewAccountForm.invalid) {
       this.isLocationLoadingResults = true;
       this.sharedService.cleanForm(this.vimNewAccountForm, 'vim');
       if (!isNullOrUndefined(this.data) && this.data !== '') {
         Object.assign(this.vimNewAccountForm.value.config, jsyaml.load(this.data.toString(), { json: true }));
       } else {
-        Object.keys(this.vimNewAccountForm.value.config).forEach((res: string) => {
+        Object.keys(this.vimNewAccountForm.value.config).forEach((res: string): void => {
           if (res !== 'location') {
+            // eslint-disable-next-line @typescript-eslint/no-dynamic-delete, security/detect-object-injection
             delete this.vimNewAccountForm.value.config[res];
           }
         });
       }
+      if (!isNullOrUndefined(this.vimNewAccountForm.value.latitude) && !isNullOrUndefined(this.vimNewAccountForm.value.longitude)) {
+        this.vimNewAccountForm.value.config.location = this.vimNewAccountForm.value.locationName + ',' +
+          this.vimNewAccountForm.value.longitude + ',' +
+          this.vimNewAccountForm.value.latitude;
+      }
 
       if (isNullOrUndefined(this.vimNewAccountForm.value.config.location)) {
         delete this.vimNewAccountForm.value.config.location;
       }
-      Object.keys(this.vimNewAccountForm.value.config).forEach((res: string) => {
+
+      Object.keys(this.vimNewAccountForm.value.config).forEach((res: string): void => {
+        // eslint-disable-next-line security/detect-object-injection
         if (isNullOrUndefined(this.vimNewAccountForm.value.config[res]) || this.vimNewAccountForm.value.config[res] === '') {
+          // eslint-disable-next-line @typescript-eslint/no-dynamic-delete, security/detect-object-injection
           delete this.vimNewAccountForm.value.config[res];
         }
       });
-      const apiURLHeader: APIURLHEADER = {
-        url: environment.VIMACCOUNTS_URL,
-        httpOptions: { headers: this.headers }
-      };
-      this.restService.postResource(apiURLHeader, this.vimNewAccountForm.value)
-        .subscribe((result: {}) => {
-          this.notifierService.notify('success', this.translateService.instant('PAGE.VIM.CREATEDSUCCESSFULLY'));
-          this.isLocationLoadingResults = false;
-          this.router.navigate(['vim/details']).catch(() => {
-            // Error Cached;
-          });
-          // Post the New Vim data and reflect in the VIM Details Page.
-        }, (error: ERRORDATA) => {
-          this.restService.handleError(error, 'post');
-          this.isLocationLoadingResults = false;
-        });
+      if (!isNullOrUndefined(this.vimID)) {
+        this.editVIM();
+      } else {
+        this.createNewVIM();
+      }
     }
   }
 
+  /** Create a new VIM Account @public */
+  public createNewVIM(): void {
+    const apiURLHeader: APIURLHEADER = {
+      url: environment.VIMACCOUNTS_URL,
+      httpOptions: { headers: this.headers }
+    };
+    delete this.vimNewAccountForm.value.locationName;
+    delete this.vimNewAccountForm.value.latitude;
+    delete this.vimNewAccountForm.value.longitude;
+    this.restService.postResource(apiURLHeader, this.vimNewAccountForm.value)
+      .subscribe((result: { id: string }): void => {
+        this.notifierService.notify('success', this.translateService.instant('PAGE.VIM.CREATEDSUCCESSFULLY'));
+        this.isLocationLoadingResults = false;
+        this.router.navigate(['vim/info/' + result.id]).catch((): void => {
+          // Error Cached;
+        });
+      }, (error: ERRORDATA): void => {
+        this.restService.handleError(error, 'post');
+        this.isLocationLoadingResults = false;
+      });
+  }
+
+  /** Create a edit VIM Account @public */
+  public editVIM(): void {
+    const apiURLHeader: APIURLHEADER = {
+      url: environment.VIMACCOUNTS_URL + '/' + this.vimID,
+      httpOptions: { headers: this.headers }
+    };
+    delete this.vimNewAccountForm.value.locationName;
+    delete this.vimNewAccountForm.value.latitude;
+    delete this.vimNewAccountForm.value.longitude;
+    this.restService.patchResource(apiURLHeader, this.vimNewAccountForm.value)
+      .subscribe((result: { id: string }): void => {
+        this.notifierService.notify('success', this.translateService.instant('PAGE.VIM.UPDATEDSUCCESSFULLY'));
+        this.isLocationLoadingResults = false;
+        this.router.navigate(['vim/info/' + this.vimID]).catch((): void => {
+          // Error Cached;
+        });
+      }, (error: ERRORDATA): void => {
+        this.restService.handleError(error, 'post');
+        this.isLocationLoadingResults = false;
+      });
+  }
   /** HandleChange function @public */
   public handleChange($event: string): void {
     this.data = $event;
@@ -263,51 +390,11 @@ export class NewVimaccountComponent implements OnInit {
 
   /** Routing to VIM Account Details Page @public */
   public onVimAccountBack(): void {
-    this.router.navigate(['vim/details']).catch(() => {
+    this.router.navigate(['vim/details']).catch((): void => {
       // Error Cached
     });
   }
 
-  /** Fetching the location with name,latitude,longitude @public */
-  public fetchLocationLatLong(value: string): void {
-    this.isLocationLoadingResults = true;
-    const newVIMLocation: VIMLOCATIONDATA[] = [];
-    const locationTrack: string = environment.MAPLATLONGAPI_URL;
-    const locationAPIURL: string = locationTrack.replace('{value}', value);
-    this.restService.getResource(locationAPIURL).subscribe((result: VIMLOCATION) => {
-      result.features.forEach((getFeturesResult: FEATURES) => {
-        if ('extent' in getFeturesResult.properties) {
-          getFeturesResult.properties.extent.forEach((extentResult: number, index: number) => {
-            if (index === 0) {
-              this.setLong = extentResult;
-            }
-            if (index === 1) {
-              this.setLat = extentResult;
-            }
-          });
-        } else {
-          getFeturesResult.geometry.coordinates.forEach((coordinateResult: number, index: number) => {
-            if (index === 0) {
-              this.setLong = coordinateResult;
-            }
-            if (index === 1) {
-              this.setLat = coordinateResult;
-            }
-          });
-        }
-        newVIMLocation.push({
-          label: getFeturesResult.properties.name + ',' + getFeturesResult.properties.state + ', ' + getFeturesResult.properties.country,
-          value: getFeturesResult.properties.name + ',' + this.setLong + ',' + this.setLat
-        });
-      });
-      this.getVIMLocation = newVIMLocation;
-      this.isLocationLoadingResults = false;
-    }, (error: ERRORDATA) => {
-      this.restService.handleError(error, 'get');
-      this.isLocationLoadingResults = false;
-    });
-  }
-
   /** Drag and drop feature and fetchind the details of files  @private */
   public filesDropped(files: FileList): void {
     if (files && files.length === 1) {
@@ -331,22 +418,28 @@ export class NewVimaccountComponent implements OnInit {
     this.fileInput.nativeElement.value = null;
   }
 
-  /** Location chnage event in select box @public */
-  public locationChange(data: { value: string }): void {
-    this.vimDetail.forEach((vimAccountData: VimAccountDetails) => {
-      if (!isNullOrUndefined(vimAccountData.config.location) && !isNullOrUndefined(data)) {
-        if (vimAccountData.config.location === data.value) {
-          this.notifierService.notify('error', this.translateService.instant('PAGE.VIMDETAILS.LOCATIONERROR'));
-          // tslint:disable-next-line: no-backbone-get-set-outside-model
-          this.vimNewAccountForm.controls.config.get('location').setValue(null);
+  /** Check data is empty or not to load config @public */
+  public checkData(): void {
+    if (this.data !== '' && this.data.length > this.configLength) {
+      // eslint-disable-next-line security/detect-non-literal-fs-filename
+      const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
+      modalRef.componentInstance.heading = this.translateService.instant('PAGE.VIMDETAILS.VIMHEADER');
+      modalRef.componentInstance.confirmationMessage = this.translateService.instant('PAGE.VIMDETAILS.VIMCONTENT');
+      modalRef.componentInstance.submitMessage = this.translateService.instant('PAGE.VIMDETAILS.VIMSUBMIT');
+      modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
+        if (result.message === CONFIGCONSTANT.done) {
+          this.loadSampleConfig();
         }
-      }
-    });
+      }).catch((): void => {
+        // Catch Navigation Error
+      });
+    } else if (this.data.length < this.configLength || this.data === '') {
+      this.loadSampleConfig();
+    }
   }
 
   /** Load sample config based on VIM type @public */
   public loadSampleConfig(): void {
-    this.clearConfig();
     if (this.selectedVimType === 'openstack') {
       this.defaults['text/x-yaml'] = jsyaml.dump(TYPEOPENSTACK);
       this.data = JSON.stringify(TYPEOPENSTACK, null, '\t');
@@ -368,22 +461,58 @@ export class NewVimaccountComponent implements OnInit {
     }
   }
 
+  /** Load sample config based on VIM type in edit @public */
+  public loadConfig(): void {
+    this.clearConfig();
+    if (this.details.vim_type === 'openstack') {
+      this.defaults['text/x-yaml'] = jsyaml.dump(this.config);
+      this.data = JSON.stringify(this.config, null, '\t');
+    } else if (this.details.vim_type === 'aws') {
+      this.defaults['text/x-yaml'] = jsyaml.dump(this.config);
+      this.data = JSON.stringify(this.config, null, '\t');
+    } else if (this.details.vim_type === 'vmware') {
+      this.defaults['text/x-yaml'] = jsyaml.dump(this.config);
+      this.data = JSON.stringify(this.config, null, '\t');
+    } else if (this.details.vim_type === 'openvim' || this.details.vim_type === 'opennebula') {
+      this.defaults['text/x-yaml'] = jsyaml.dump(this.config);
+      this.data = JSON.stringify(this.config, null, '\t');
+    } else if (this.details.vim_type === 'azure' || this.details.vim_type === 'opennebula') {
+      this.defaults['text/x-yaml'] = jsyaml.dump(this.config);
+      this.data = JSON.stringify(this.config, null, '\t');
+    } else {
+      this.defaults['text/x-yaml'] = jsyaml.dump(this.config);
+      this.data = JSON.stringify(this.config, null, '\t');
+    }
+  }
+
   /** Clear config parameters @public */
   public clearConfig(): void {
-    this.defaults['text/x-yaml'] = '';
-    this.data = '';
-    this.fileInput.nativeElement.value = null;
+    this.check = true;
+    if (this.data !== '' && this.data.length > this.configLength) {
+      // eslint-disable-next-line security/detect-non-literal-fs-filename
+      const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
+      modalRef.componentInstance.heading = this.translateService.instant('PAGE.VIMDETAILS.VIMHEADER');
+      modalRef.componentInstance.confirmationMessage = this.translateService.instant('PAGE.VIMDETAILS.CLEARCONTENT');
+      modalRef.componentInstance.submitMessage = this.translateService.instant('PAGE.VIMDETAILS.VIMSUBMIT');
+      modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
+        if (result.message === CONFIGCONSTANT.done) {
+          this.defaults['text/x-yaml'] = '';
+          this.data = '';
+          this.fileInput.nativeElement.value = null;
+        }
+      }).catch((): void => {
+        // Catch Navigation Error
+      });
+    } else {
+      this.defaults['text/x-yaml'] = '';
+      this.data = '';
+      this.fileInput.nativeElement.value = null;
+    }
   }
 
-  /** Method to get VIM details @private */
-  private getVIMDetails(): void {
-    this.isLocationLoadingResults = true;
-    this.restService.getResource(environment.VIMACCOUNTS_URL).subscribe((vimAccountsData: VimAccountDetails[]) => {
-      this.vimDetail = vimAccountsData;
-      this.isLocationLoadingResults = false;
-    }, (error: ERRORDATA) => {
-      this.restService.handleError(error, 'get');
-      this.isLocationLoadingResults = false;
-    });
+  /** Used to get the AbstractControl of controlName passed @private */
+  private getFormControl(controlName: string): AbstractControl {
+    // eslint-disable-next-line security/detect-object-injection
+    return this.vimNewAccountForm.controls[controlName];
   }
 }