When feature toggle is active then SDNC preload files is enable.

Issue-ID: VID-752

Change-Id: I96ef914bfe37d82da20085227b930523fcdba8fc
Signed-off-by: Yoav Schneiderman <yoav.schneiderman@intl.att.com>
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html
index 26362eb..fe7744e 100644
--- a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html
+++ b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html
@@ -8,4 +8,9 @@
          data-toggle="toggle">
   <label class="checkbox-label"
          for="{{data?.dataTestId}}">{{data?.displayName}}</label>
+  <div *ngFor="let extraContent of data?.extraContents" class="form-conrtols">
+    <div [ngSwitch]="extraContent.type">
+      <upload-files *ngSwitchCase="'UPLOAD_FILE'" [uploadFilesModel]="extraContent" [form]="form"></upload-files>
+    </div>
+  </div>
 </div>
diff --git a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss
index 005e28c..81180e0 100644
--- a/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss
+++ b/vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss
@@ -11,6 +11,7 @@
 .details-item label {
   position: relative;
   cursor: pointer;
+  float: left;
 }
 
 .details-item label:before {
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts
index acfaf78..83f7227 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts
@@ -133,13 +133,14 @@
     })
   };
 
-  getSDNCControl = (instance: any): FormControlModel => {
+  getSDNCControl = (instance: any, extraContents? : object[]): FormControlModel => {
     return new CheckboxFormControl({
       controlName: SDN_C_PRE_LOAD,
       displayName: 'SDN-C pre-load',
       dataTestId: 'sdncPreLoad',
       value: instance ? instance.sdncPreLoad : false,
-      validations: [new ValidatorModel(ValidatorOptions.required, 'is required')]
+      validations: [new ValidatorModel(ValidatorOptions.required, 'is required')],
+      extraContents
     })
   };
 
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts
index b3bb1fe..49deb3a 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts
@@ -4,7 +4,7 @@
 import {ControlGeneratorUtil, SDN_C_PRE_LOAD} from "../control.generator.util.service";
 import {AaiService} from "../../../../services/aaiService/aai.service";
 import {GenericFormService} from "../../generic-form.service";
-import {FormBuilder} from "@angular/forms";
+import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
 import {LogService} from "../../../../utils/log/log.service";
 import {
   FormControlModel,
@@ -16,6 +16,7 @@
 import {VfModuleInstance} from "../../../../models/vfModuleInstance";
 import {VfModule} from "../../../../models/vfModule";
 import {SharedControllersService} from "../sharedControlles/shared.controllers.service";
+import {AppState} from "../../../../store/reducers";
 import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
 
 class MockAppStore<T> {
@@ -919,6 +920,7 @@
   let injector;
   let service: VfModuleControlGenerator;
   let httpMock: HttpTestingController;
+  let store : NgRedux<AppState>;
 
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
@@ -939,6 +941,7 @@
     injector = getTestBed();
     service = injector.get(VfModuleControlGenerator);
     httpMock = injector.get(HttpTestingController);
+    store = injector.get(NgRedux);
     jest.spyOn(console, 'error');
 
   })().then(done).catch(done.fail));
@@ -1164,5 +1167,29 @@
       expect(controls[i].controlName).toEqual(orderedControls[i]);
     }
   });
+
+
+  test('when flag is active - response should contains upload file', ()=>{
+    spyOn(store, 'getState').and.returnValue( {
+      "global": {
+        "flags": {
+          "FLAG_2006_VFM_SDNC_PRELOAD_FILES" : true
+        }
+      }
+    });
+
+    const extraContent = service.getSdncExtraContents();
+    console.log("extraContent", extraContent);
+    const uploadFileData = <any>extraContent[0];
+
+    expect(uploadFileData.type).toEqual('UPLOAD_FILE');
+    expect(uploadFileData.dataTestId).toEqual('sdnc_pereload_upload_link');
+    expect(uploadFileData.uploadMethod).toBeDefined();
+    expect(uploadFileData.isDisabled).toBeDefined();
+    expect(uploadFileData.onSuccess).toBeDefined();
+    expect(uploadFileData.onFailed).toBeDefined();
+
+  })
+
 });
 
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts
index b00312d..5189af0 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts
+++ b/vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts
@@ -3,7 +3,7 @@
 import {AaiService} from "../../../../services/aaiService/aai.service";
 import {NgRedux} from "@angular-redux/store";
 import {HttpClient} from "@angular/common/http";
-import {ControlGeneratorUtil} from "../control.generator.util.service";
+import {ControlGeneratorUtil, SDN_C_PRE_LOAD} from "../control.generator.util.service";
 import {
   CustomValidatorOptions,
   FormControlModel,
@@ -20,6 +20,8 @@
 import {VnfInstance} from "../../../../models/vnfInstance";
 import * as _ from 'lodash';
 import {SharedControllersService} from "../sharedControlles/shared.controllers.service";
+import {MessageModal} from "../../../messageModal/message-modal.service";
+import {ButtonType} from "../../../customModal/models/button.type";
 import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
 
 export enum FormControlNames {
@@ -36,7 +38,7 @@
 export class VfModuleControlGenerator {
   aaiService: AaiService;
   vfModuleModel: VfModule;
-  isUpdateMode : boolean;
+  isUpdateMode: boolean;
 
   constructor(private genericFormService: GenericFormService,
               private _basicControlGenerator: ControlGeneratorUtil,
@@ -54,7 +56,7 @@
     if (isUpdateMode && this.store.getState().service.serviceInstance[serviceId] &&
       _.has(this.store.getState().service.serviceInstance[serviceId].vnfs, vnfStoreKey) &&
       _.has(this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules, UUIDData['modelName'])) {
-       vfModuleInstance = Object.assign({},this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules[UUIDData['modelName']][UUIDData['vFModuleStoreKey']]);
+      vfModuleInstance = Object.assign({}, this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules[UUIDData['modelName']][UUIDData['vFModuleStoreKey']]);
     }
     return vfModuleInstance;
   };
@@ -65,11 +67,11 @@
     return vfModule;
   }
 
-  getMacroFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] {
+  getMacroFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData: Object, isUpdateMode: boolean): FormControlModel[] {
     this.isUpdateMode = isUpdateMode;
     this.extractVfAccordingToVfModuleUuid(serviceId, uuidData);
     if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) {
-      if(isUpdateMode){
+      if (isUpdateMode) {
         this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId);
         return [];
       }
@@ -85,7 +87,7 @@
     if (!_.isNil(vfModuleModel)) {
       result = this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, false);
     }
-    if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
+    if (this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
       result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance);
     }
     return result;
@@ -99,7 +101,7 @@
     return new VNFModel(model);
   }
 
-  pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean) :FormControlModel[]{
+  pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean): FormControlModel[] {
     result.push(this.getInstanceName(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming));
     if (this.vfModuleModel.volumeGroupAllowed) {
       result.push(this.getVolumeGroupData(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming, isALaCarte));
@@ -107,16 +109,16 @@
     return result;
   }
 
-  getAlaCarteFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] {
+  getAlaCarteFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData: Object, isUpdateMode: boolean): FormControlModel[] {
     this.isUpdateMode = isUpdateMode;
     this.extractVfAccordingToVfModuleUuid(serviceId, uuidData);
     if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) {
-      if(isUpdateMode){
+      if (isUpdateMode) {
         this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId);
         return [];
       }
     }
-    const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey] ;
+    const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey];
     const vnfModel = this.newVNFModel(serviceId, vnf);
 
     const vfModuleInstance = this._basicControlGenerator.retrieveInstanceIfUpdateMode(this.store, this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode));
@@ -126,26 +128,64 @@
     result.push(this._sharedControllersService.getLegacyRegion(vfModuleInstance));
     result.push(this._sharedControllersService.getTenantControl(serviceId, vfModuleInstance));
     result.push(this._sharedControllersService.getRollbackOnFailureControl(vfModuleInstance));
-    result.push(this._sharedControllersService.getSDNCControl(vfModuleInstance));
-    if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
+    result.push(this._sharedControllersService.getSDNCControl(vfModuleInstance, this.getSdncExtraContents()));
+    if (this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
       result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance);
     }
     return result;
   }
 
-  getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel {
-    let formControlModel:FormControlModel = this._sharedControllersService.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, this.vfModuleModel);
-    formControlModel.onBlur = (event, form : FormGroup) => {
-        if(!_.isNil(form.controls['volumeGroupName'])&& event.target.value.length > 0){
-          form.controls['volumeGroupName'].setValue(event.target.value + "_vol");
+  getSdncExtraContents() : object[] {
+    return _.compact([
+      !!this.store.getState().global.flags['FLAG_2006_VFM_SDNC_PRELOAD_FILES'] ? {
+        type: 'UPLOAD_FILE',
+        dataTestId: 'sdnc_pereload_upload_link',
+        uploadMethod: (form: FormGroup) : Promise<boolean> => {
+          // this -> files item
+          return this._aaiService.sdncPreload().toPromise()
+            .then((response : boolean)=>{
+              return response;
+            }).catch(err => {
+              return false;
+            });
+        },
+        isDisabled: (form: FormGroup): boolean => {
+          return !form.controls[SDN_C_PRE_LOAD].value;
+        },
+        onSuccess: (form: FormGroup): void => {
+          MessageModal.showMessageModal({
+            text: 'The pre-load file(s) have been uploaded successfully.',
+            type: "success",
+            title: 'Success',
+            buttons: [{type: ButtonType.success, size: 'large', text: 'OK', closeModal: true}]
+          })
+        },
+        onFailed: (form: FormGroup) : void=> {
+          MessageModal.showMessageModal({
+            text: 'Failed to upload one or more of the files, please retry.',
+            type: "error",
+            title: 'Failure',
+            buttons: [{type: ButtonType.error, size: 'large', text: 'OK', closeModal: true}]
+          })
         }
-      };
+      } : null
+    ]);
+  }
+
+
+  getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel {
+    let formControlModel: FormControlModel = this._sharedControllersService.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, this.vfModuleModel);
+    formControlModel.onBlur = (event, form: FormGroup) => {
+      if (!_.isNil(form.controls['volumeGroupName']) && event.target.value.length > 0) {
+        form.controls['volumeGroupName'].setValue(event.target.value + "_vol");
+      }
+    };
 
     return formControlModel;
   }
 
   getDefaultVolumeGroupName(instance: any, isEcompGeneratedNaming: boolean): string {
-    if ((!_.isNil(instance) && instance.volumeGroupName))  {
+    if ((!_.isNil(instance) && instance.volumeGroupName)) {
       return instance.volumeGroupName;
     }
     if (isEcompGeneratedNaming) {
@@ -165,12 +205,12 @@
       displayName: 'Volume Group Name',
       dataTestId: 'volumeGroupName',
       validations: validations,
-      tooltip : 'When filled, VID will create a Volume Group by this name and associate with this module.\n' +
-                'When empty, the module is created without a Volume Group.',
-      isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming,isALaCarte),
+      tooltip: 'When filled, VID will create a Volume Group by this name and associate with this module.\n' +
+        'When empty, the module is created without a Volume Group.',
+      isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming, isALaCarte),
       value: this.getDefaultVolumeGroupName(instance, isEcompGeneratedNaming),
       onKeypress: (event) => {
-        const pattern:RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX;
+        const pattern: RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX;
         if (pattern) {
           if (!pattern.test(event['key'])) {
             event.preventDefault();
@@ -182,7 +222,7 @@
   }
 
   private shouldVGNameBeVisible(isEcompGeneratedNaming: boolean, isALaCarte: boolean) {
-    if((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte){
+    if ((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte) {
       return true;
     }
     return false;
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html
index edf8682..627f642 100644
--- a/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html
+++ b/vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html
@@ -3,7 +3,7 @@
     <div *ngFor="let formControl of formControls" class="form-conrtols">
       <div [ngSwitch]="formControl.type">
         <form-control-input  *ngSwitchCase="'INPUT'"   [data]="formControl" [form]="dynamicFormGroup"></form-control-input>
-        <checkbox-form-control *ngSwitchCase="'CHECKBOX'"  [data]="formControl" [form]="dynamicFormGroup" ></checkbox-form-control>
+        <checkbox-form-control *ngSwitchCase="'CHECKBOX'"  [data]="formControl" [form]="dynamicFormGroup"></checkbox-form-control>
         <dropdown-form-control *ngSwitchCase="'DROPDOWN'" [data]="formControl" [form]="dynamicFormGroup" ></dropdown-form-control>
         <file-form-control *ngSwitchCase="'FILE'" [data]="formControl" [form]="dynamicFormGroup"></file-form-control>
         <multiselect-form-control *ngSwitchCase="'MULTI_SELECT'"
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html
new file mode 100644
index 0000000..6f59c0c
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html
@@ -0,0 +1,15 @@
+<div>
+  <a [attr.data-tests-id]="uploadFilesModel.dataTestId"
+     (click)="uploadFilesTrigger()"
+     href="javascript:void(0)"
+     class="upload-text"
+     [class.disabled]="uploadFilesModel.isDisabled &&  uploadFilesModel.isDisabled(form)">{{uploadFilesModel.uploadText || 'Upload'}}</a>
+  <span class="hide-span">
+     <input
+       type="file"
+       #fileInput
+       ng2FileSelect
+       [uploader]="uploader"
+       [attr.data-tests-id]="uploadFilesModel.dataTestId + '-input'"/>
+  </span>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss
new file mode 100644
index 0000000..ce9e14f
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss
@@ -0,0 +1,23 @@
+.upload-text {
+  margin-left: 30px;
+  font-family: OpenSans-Semibold;
+  font-size: 14px;
+  line-height: 23px;
+}
+
+a.disabled {
+  color: gray;
+  cursor: not-allowed;
+  text-decoration: underline;
+}
+
+.hide-span {
+  visibility: hidden;
+  position: absolute;
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  border: none;
+  margin: 0;
+  padding: 0
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts
new file mode 100644
index 0000000..803d5d0
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts
@@ -0,0 +1,41 @@
+import {Component, ElementRef, Input, OnInit, ViewChild} from "@angular/core";
+import {FileItem, FileUploader} from "ng2-file-upload";
+import {UploadFilesLinkModel} from "./upload-files-link.model";
+import {FormGroup} from "@angular/forms";
+
+@Component({
+  selector: 'upload-files',
+  templateUrl: './upload-files-link.component.html',
+  styleUrls: ['./upload-files-link.component.scss']
+})
+export class UploadFilesLinkComponent implements OnInit {
+  uploader: FileUploader;
+  @Input() uploadFilesModel: UploadFilesLinkModel;
+  @Input() form: FormGroup;
+  @ViewChild('fileInput', {static: false}) fileInput: ElementRef;
+
+  ngOnInit(): void {
+    this.uploader = new FileUploader({});
+
+    this.uploader.onAfterAddingAll = async (files: FileItem[]) => {
+      const result = await this.uploadFilesModel.uploadMethod.call(files, this.form);
+      if (result && this.uploadFilesModel.onSuccess) {
+        this.uploadFilesModel.onSuccess.call(this.form);
+      } else if (!result && this.uploadFilesModel.onFailed) {
+        this.uploadFilesModel.onFailed.call(this.form);
+      }
+      this.uploadFilesModel.uploadText = result ? 'Upload another' : 'Upload'
+    };
+    this.resetUpload();
+  }
+
+  resetUpload(): void {
+    this.fileInput.nativeElement.value = '';
+  }
+
+  uploadFilesTrigger() {
+    if (this.uploadFilesModel.isDisabled && !this.uploadFilesModel.isDisabled(this.form)) {
+      this.fileInput.nativeElement.click();
+    }
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts
new file mode 100644
index 0000000..beb54f4
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts
@@ -0,0 +1,30 @@
+import {FileItem} from "ng2-file-upload";
+
+export class UploadFilesLinkModel {
+  uploadText?: string;
+
+  /*********************************************************************
+   Implement success method - run after uploadMethod return true result
+   **********************************************************************/
+  onSuccess?: (...args) => void;
+
+  /*********************************************************************
+   Implement failed method - run after uploadMethod return false result
+   **********************************************************************/
+  onFailed?: (...args) => void;
+
+  /*********************************************************************************
+   Implement upload method and return the upload result status (false/true)
+   *********************************************************************************/
+  uploadMethod: (file: FileItem[], ...args) => Promise<boolean>;
+
+  /********************************
+   Should upload file be disabled
+   ********************************/
+  isDisabled?: (...args) => boolean;
+
+  /********************************
+   a tag data test id
+   ********************************/
+  dataTestId : string;
+}
diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts
new file mode 100644
index 0000000..d291440
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts
@@ -0,0 +1,15 @@
+import {ButtonType} from "../customModal/models/button.type";
+
+export class MessageModalModel {
+  title : string;
+  text : string;
+  type : 'error' | 'info' | 'success';
+  buttons :  {text: string, size: string, type : ButtonType, closeModal: boolean}[];
+
+  constructor( title : string, text : string, type , buttons : {text: string, size: string, type : ButtonType, closeModal: boolean}[]){
+    this.title = title;
+    this.text = text;
+    this.type = type;
+    this.buttons = buttons;
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts
new file mode 100644
index 0000000..ffaccb1
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts
@@ -0,0 +1,56 @@
+import {MessageModal} from "./message-modal.service";
+import {getTestBed, TestBed} from "@angular/core/testing";
+import {SdcUiCommon} from "onap-ui-angular";
+import each from "jest-each";
+import {MessageBoxService} from "../messageBox/messageBox.service";
+import {MessageModalModel} from "./message-modal.model";
+import {MessageBoxData} from "../messageBox/messageBox.data";
+
+
+describe('Message Modal Service', () => {
+  let injector;
+  let service: MessageModal;
+
+  beforeAll(done => (async () => {
+    TestBed.configureTestingModule({
+      imports: [],
+      providers: [MessageModal]
+    });
+    await TestBed.compileComponents();
+
+    injector = getTestBed();
+    service = injector.get(MessageModal);
+  })().then(done).catch(done.fail));
+
+
+  each([
+    ["error", SdcUiCommon.ModalType.error],
+    ["info", SdcUiCommon.ModalType.info],
+    ["success", SdcUiCommon.ModalType.success]
+  ]).test('getModalType with type %s should return %s', (inputMessageType, expectedResult) => {
+
+    let message = {
+      type: inputMessageType
+    };
+
+    const type = MessageModal.getModalType(<any>message)
+    expect(type).toEqual(expectedResult);
+  });
+
+  test('showMessageModal should call open modal with all data' , async (done)=>{
+    spyOn(MessageBoxService.openModal, 'next');
+    let message : MessageModalModel  = new MessageModalModel('title', 'text',  "success", []);
+
+    MessageModal.showMessageModal(message);
+    setTimeout(()=>{
+      const messageBoxData = new MessageBoxData( message.title,
+        message.text,
+        SdcUiCommon.ModalType.success,
+        SdcUiCommon.ModalSize.medium,
+        message.buttons)
+      expect(MessageBoxService.openModal.next).toHaveBeenCalledWith(messageBoxData);
+      done();
+    }, 500)
+  });
+
+});
diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts
new file mode 100644
index 0000000..e1f85bd
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts
@@ -0,0 +1,39 @@
+import {Injectable} from "@angular/core";
+import {MessageBoxService} from '../messageBox/messageBox.service';
+import {MessageBoxData} from '../messageBox/messageBox.data';
+import {SdcUiCommon} from "onap-ui-angular";
+import {MessageModalModel} from "./message-modal.model";
+
+@Injectable()
+export class MessageModal {
+  static showMessageModal(message: MessageModalModel): void {
+    setTimeout(() => {
+        let messageBoxData: MessageBoxData = new MessageBoxData(
+          message.title,
+          message.text,
+          this.getModalType(message),
+          SdcUiCommon.ModalSize.medium,
+          message.buttons);
+        MessageBoxService.openModal.next(messageBoxData);
+      }
+      , 500);
+  };
+
+
+  static getModalType = (message: MessageModalModel): string => {
+    switch (message.type) {
+      case "error": {
+        return SdcUiCommon.ModalType.error
+      }
+      case "info": {
+        return  SdcUiCommon.ModalType.info;
+      }
+      case "success":  {
+        return  SdcUiCommon.ModalType.success;
+      }
+    }
+  };
+}
+
+
+
diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts
index f505b56..1675917 100644
--- a/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts
+++ b/vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts
@@ -1,11 +1,13 @@
 import {FormControlModel} from "./formControl.model";
 import {FormControlType} from "./formControlTypes.enum";
+import * as _ from "lodash";
 
 export class CheckboxFormControl extends FormControlModel{
-
+  extraContents : object[];
   constructor(data) {
     super(data);
     this.type = FormControlType.CHECKBOX;
     this.validations = [];
+    this.extraContents = !_.isNil(data.extraContents)  ? data.extraContents : null;
   }
 }
diff --git a/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts b/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts
index 2411654..b3a53d9 100644
--- a/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts
+++ b/vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts
@@ -43,6 +43,7 @@
     this.preventionsAttribute = data.preventionsAttribute || [];
     this.onBlur = function(){};
     this.onChange = data.onChange ? data.onChange: function () {}
+
   }
 
   isRequired() : boolean {
diff --git a/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts b/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts
index 1cc5593..9026a56 100644
--- a/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts
+++ b/vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts
@@ -44,6 +44,11 @@
 
   }
 
+  sdncPreload(): Observable<boolean> {
+    let pathQuery: string = Constants.Path.PRE_LOAD;
+    return this.http.post<boolean>(pathQuery, {})
+  }
+
   getServiceModelById = (serviceModelId: string): Observable<any> => {
     if (_.has(this.store.getState().service.serviceHierarchy, serviceModelId)) {
       return of(<any> JSON.parse(JSON.stringify(this.store.getState().service.serviceHierarchy[serviceModelId])));
diff --git a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
index db270de..722deca 100644
--- a/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
+++ b/vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
@@ -15,6 +15,7 @@
   FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS ='FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS',
   FLAG_2004_INSTANTIATION_STATUS_FILTER ='FLAG_2004_INSTANTIATION_STATUS_FILTER',
   FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE = 'FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE',
+  FLAG_2006_VFM_SDNC_PRELOAD_FILES = 'FLAG_2006_VFM_SDNC_PRELOAD_FILES',
   FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO = 'FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO',
   FLAG_2004_INSTANTIATION_TEMPLATES_POPUP = 'FLAG_2004_INSTANTIATION_TEMPLATES_POPUP',
   FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY= 'FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY'
diff --git a/vid-webpack-master/src/app/shared/shared.module.ts b/vid-webpack-master/src/app/shared/shared.module.ts
index 08b7fe5..bae7c11 100644
--- a/vid-webpack-master/src/app/shared/shared.module.ts
+++ b/vid-webpack-master/src/app/shared/shared.module.ts
@@ -93,6 +93,9 @@
 import {TooltipTemplateComponent} from "./components/customTooltip/custom-tooltip.component";
 import {TooltipDirective} from "./components/customTooltip/tooltip.directive";
 import {SdcUiComponentsModule} from "onap-ui-angular";
+import {UploadFilesLinkComponent} from "./components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component";
+import { FileUploadModule } from 'ng2-file-upload';
+import {MessageModal} from "./components/messageModal/message-modal.service";
 
 
 
@@ -111,7 +114,8 @@
     AngularMultiSelectModule,
     BootstrapModalModule,
     DataTableModule,
-    ModalModule.forRoot()
+    ModalModule.forRoot(),
+    FileUploadModule
   ],
   declarations: [
     PopoverComponent,
@@ -156,7 +160,8 @@
     CustomModalButtonComponent,
     LoaderComponent,
     SvgIconComponent,
-    TooltipTemplateComponent
+    TooltipTemplateComponent,
+    UploadFilesLinkComponent
   ],
   exports: [
     PopoverComponent,
@@ -197,7 +202,8 @@
     CustomModalButtonComponent,
     LoaderComponent,
     SvgIconComponent,
-    TooltipTemplateComponent
+    TooltipTemplateComponent,
+    UploadFilesLinkComponent
   ],
   entryComponents : [
     GenericFormPopupComponent,
@@ -248,7 +254,8 @@
     ModelInformationService,
     MultiselectFormControlService,
     InstantiationTemplatesModalService,
-    LoaderService
+    LoaderService,
+    MessageModal
   ]
 })
 export class SharedModule {
diff --git a/vid-webpack-master/src/app/shared/utils/constants.ts b/vid-webpack-master/src/app/shared/utils/constants.ts
index da717c8..01466f1 100644
--- a/vid-webpack-master/src/app/shared/utils/constants.ts
+++ b/vid-webpack-master/src/app/shared/utils/constants.ts
@@ -97,6 +97,7 @@
     public static SERVICE_MODEL_ID = 'serviceModelId';
     public static SERVICES_RETRY_TOPOLOGY = '../../asyncInstantiation/bulkForRetry';
     public static INSTANTIATION_TEMPLATE_TOPOLOGY = '../../instantiationTemplates/templateTopology';
+    public static PRE_LOAD = '../../preload';
     public static CONFIGURATION_PATH = '../../get_property/{name}/defaultvalue';
     public static SERVICES_JOB_AUDIT_PATH = '/auditStatus';
     public static SERVICES_PROBE_PATH = "../../probe";
diff --git a/vid-webpack-master/src/styles.scss b/vid-webpack-master/src/styles.scss
index f170f35..1d332ed 100644
--- a/vid-webpack-master/src/styles.scss
+++ b/vid-webpack-master/src/styles.scss
@@ -239,4 +239,6 @@
   display: none !important;
 }
 
-
+sdc-modal {
+  z-index:  10000 !important;
+}