New Angular UI from 1806

Change-Id: I39c160db0e0a6ec2e587ccf007ee1b23c6a08666
Issue-ID: VID-208
Signed-off-by: Sonsino, Ofir (os0695) <os0695@intl.att.com>
diff --git a/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts
new file mode 100644
index 0000000..fd58b65
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts
@@ -0,0 +1,27 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector : 'custom-ellipsis',
+  template: `
+    <span 
+          class="ellipsis"
+          id="{{id}}"
+          tooltip="{{value}}">{{value}}</span>`,
+  styles : [
+    `
+      .ellipsis {
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: inline-block;
+        width: 99%;
+        text-align: left;
+      }
+    `
+  ]
+})
+export class EllipsisComponent {
+  @Input() value : string;
+  @Input() id : string;
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/error/error.component.service.ts b/vid-webpack-master/src/app/shared/components/error/error.component.service.ts
new file mode 100644
index 0000000..35b83f0
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/error/error.component.service.ts
@@ -0,0 +1,35 @@
+import {Injectable} from "@angular/core";
+import {Subject} from "rxjs/Subject";
+import { MessageBoxService } from '../messageBox/messageBox.service';
+import { MessageBoxData, ModalSize, ModalType } from '../messageBox/messageBox.data';
+
+@Injectable()
+export class ErrorService {
+  static showErrorWithMessage(error : ErrorMessage) : void {
+    setTimeout(()=>{
+        let messageBoxData : MessageBoxData = new MessageBoxData(
+          error.title,  // modal title
+          error.text,
+
+          ModalType.error,
+          ModalSize.medium,
+          [
+            {text:"Close", size:"large", closeModal:true}
+          ]);
+        MessageBoxService.openModal.next(messageBoxData);
+      }
+      ,500);
+  }
+}
+
+export class ErrorMessage {
+  title : string;
+  text : string;
+  errorNumber : number;
+
+  constructor( title : string, text : string,errorNumber : number){
+    this.title = title;
+    this.text = text;
+    this.errorNumber = errorNumber;
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.html b/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.html
new file mode 100644
index 0000000..daa35e6
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.html
@@ -0,0 +1,4 @@
+<div  *ngIf="message">
+    <span class="icon-alert"></span>
+    <span class="message">{{message}}</span>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.scss b/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.scss
new file mode 100644
index 0000000..d174f51
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.scss
@@ -0,0 +1,14 @@
+.icon-alert {
+  margin-top: 10px;
+  &:before {
+    content: "\e904";
+    font-size: 16px;
+    color: #cf2a2a;
+  }
+}
+
+.message {
+  font-size: 12px;
+  line-height: 14px;
+  color: #cf2a2a;
+}
diff --git a/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.ts b/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.ts
new file mode 100644
index 0000000..a20b260
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formControlError/formControlError.component.ts
@@ -0,0 +1,10 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector : 'form-control-error',
+  templateUrl : 'formControlError.component.html',
+  styleUrls : ['formControlError.component.scss']
+})
+export class FormControlErrorComponent {
+  @Input() message = null;
+}
diff --git a/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.html b/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.html
new file mode 100644
index 0000000..4c794e6
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.html
@@ -0,0 +1,10 @@
+<div *ngIf="message" class="row row-padding">
+  <div class="col-md-2 icon-div"><span class="icon-alert"></span></div>
+  <div class="col-md-10 left-align parentbox">
+    <div class="childbox">
+      <span>{{message}}</span>
+    </div>
+  </div>
+</div>
+
+
diff --git a/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.scss b/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.scss
new file mode 100644
index 0000000..5271cad
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.scss
@@ -0,0 +1,48 @@
+.icon-alert {
+  margin-top: 10px;
+  &:before {
+    content: "\e904";
+    font-size: 30px;
+    color: #ffffff;
+  }
+}
+
+.icon-div {
+  background: rgb(207,41,41);
+  text-align: center;
+  padding-top: 18px;
+  width: 77px;
+  height: 110px;
+  float: left;
+}
+
+
+.error-title {
+  color: #cf2a2a;
+}
+
+.row-padding {
+  margin-left: 0 !important;
+  margin-right: 0 !important;
+}
+
+.left-align {
+  text-align: left;
+}
+
+.parentbox {
+  padding-right: 0;
+}
+
+.parentbox:before {
+  content: ' ';
+  display: inline-block;
+  vertical-align: middle;
+  height: 100%;
+}
+
+.childbox {
+  color: #cf2a2a;
+  display: inline-block;
+  vertical-align: middle;
+}
diff --git a/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.ts b/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.ts
new file mode 100644
index 0000000..0c0516a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/formGeneralErrors/formGeneralErrors.component.ts
@@ -0,0 +1,11 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector : 'form-general-error',
+  templateUrl : 'formGeneralErrors.component.html',
+  styleUrls : ['formGeneralErrors.component.scss']
+})
+
+export class FormGeneralErrorsComponent {
+  @Input() message : string = null;
+}
diff --git a/vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts
new file mode 100644
index 0000000..08e199c
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts
@@ -0,0 +1,50 @@
+/************************************************************************************************
+ * @Component: Message box component
+ * In order to use component you need to do a number of things:
+ *  1) Inside your component constructor you need to add listener to the button trigger.
+ *  2) Inside the listener you should write your callback logic.
+ *
+ *  Example:
+ *   @Component({
+ *    selector : 'some-component'
+ *    ...
+ *   })
+ *
+ *   export class SomeComponent {
+ *      openModal() : void {
+ *        let messageBoxData : MessageBoxData = new MessageBoxData(
+ *            "title",  // modal title
+ *            "message", ModalType.alert, // modal type
+  *           [
+                {text:"Save", size:"'x-small'",  callback: this.someFunction.bind(this), closeModal:true},
+                {text:"Cancel", size:"'x-small'", closeModal:true}
+          ]);
+ *
+ *        MessageBoxService.openModal.next(messageBoxData); // open modal
+ *      }
+ *   }
+
+ ************************************************************************************************/
+
+
+import { Component } from '@angular/core';
+import { MessageBoxData} from './messageBox.data';
+import { MessageBoxService } from './messageBox.service';
+import { SdcUiComponents } from 'sdc-ui/lib/angular';
+
+@Component({
+  selector: 'message-box',
+  template: '<div id="message-box"></div>'
+})
+
+export class MessageBoxComponent {
+  modalService: SdcUiComponents.ModalService;
+
+  constructor(modalService: SdcUiComponents.ModalService, private _messageBoxService : MessageBoxService) {
+    this.modalService = modalService;
+    MessageBoxService.openModal.subscribe((messageBoxData: MessageBoxData) => {
+      modalService.openModal(this._messageBoxService.setConfig(messageBoxData))
+    });
+  }
+}
+
diff --git a/vid-webpack-master/src/app/shared/components/messageBox/messageBox.data.ts b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.data.ts
new file mode 100644
index 0000000..165140b
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.data.ts
@@ -0,0 +1,51 @@
+import { Subject } from 'rxjs/Subject';
+
+export class  MessageBoxData {
+  title?: string;
+  message?: string;
+  size : ModalSize;
+  type: ModalType;
+  buttons: Array<IModalButtonComponent>;
+
+  constructor(title: string, message: string, type: ModalType, size : ModalSize, buttons: Array<IModalButtonComponent>) {
+    this.title = title;
+    this.message = message;
+    this.size = size;
+    this.type = type;
+    this.buttons = buttons;
+  }
+}
+
+export interface IModalConfig {
+  size?: string;
+  title?: string;
+  message?: string;
+  buttons?: Array<IModalButtonComponent>;
+  type?: string;
+}
+export interface IButtonComponent {
+  text: string;
+  disabled?: boolean;
+  type?: string;
+  size?: string;
+}
+export interface IModalButtonComponent extends IButtonComponent {
+  callback?: Function;
+  closeModal?: boolean;
+}
+export  enum ModalType {
+  alert = "alert",
+  error = "error",
+  standard = "info",
+  custom = "custom",
+}
+export enum ModalSize {
+  xlarge = "xl",
+  large = "l",
+  medium = "md",
+  small = "sm",
+  xsmall = "xsm",
+}
+
+
+
diff --git a/vid-webpack-master/src/app/shared/components/messageBox/messageBox.service.spec.ts b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.service.spec.ts
new file mode 100644
index 0000000..89562ac
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.service.spec.ts
@@ -0,0 +1,49 @@
+import { TestBed, getTestBed } from '@angular/core/testing';
+import {
+  HttpClientTestingModule,
+  HttpTestingController
+} from '@angular/common/http/testing';
+
+import { MessageBoxService } from './messageBox.service';
+import {MessageBoxData, ModalSize, ModalType } from './messageBox.data';
+
+describe('MessageBoxService', () => {
+  let injector;
+  let service: MessageBoxService;
+  let httpMock: HttpTestingController;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      imports: [HttpClientTestingModule],
+      providers: [MessageBoxService]
+    });
+
+    injector = getTestBed();
+    service = injector.get(MessageBoxService);
+    httpMock = injector.get(HttpTestingController);
+  });
+
+  describe('#setConfig', () => {
+    it('should return <IModalConfig>', (done: DoneFn) => {
+      let title = "Delete Instantiation";
+      let message = "You are about to stop the instantiation process of this service. \nAll data will be lost. Are you sure you want to stop?";
+      let messageBoxData : MessageBoxData = new MessageBoxData(
+        title,
+        message,
+        ModalType.alert,
+        ModalSize.medium,
+        [
+          {text:"Stop Instantiation", size:"large", closeModal:true},
+          {text:"Cancel", size:"medium", closeModal:true}
+        ]);
+
+      let result = service.setConfig(messageBoxData);
+      expect(result.title).toEqual(title);
+      expect(result.message).toEqual(message);
+      expect(result.buttons.length).toEqual(2);
+      expect(result.type).toEqual(ModalType.alert);
+      expect(result.size).toEqual(ModalSize.medium);
+      done();
+    });
+  });
+});
diff --git a/vid-webpack-master/src/app/shared/components/messageBox/messageBox.service.ts b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.service.ts
new file mode 100644
index 0000000..eaa012d
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/messageBox/messageBox.service.ts
@@ -0,0 +1,18 @@
+import { Injectable } from '@angular/core';
+import { Subject } from 'rxjs/Subject';
+import { IModalConfig, MessageBoxData, ModalSize, ModalType } from './messageBox.data';
+
+@Injectable()
+export class MessageBoxService {
+  static openModal: Subject<MessageBoxData> = new Subject<MessageBoxData>();
+  setConfig(messageBoxData: MessageBoxData) : IModalConfig{
+    return {
+      size : ModalSize.medium,
+      title : messageBoxData.title,
+      type : messageBoxData.type,
+      message : messageBoxData.message,
+      buttons: messageBoxData.buttons
+    };
+  }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/model-information/model-information.component.ts b/vid-webpack-master/src/app/shared/components/model-information/model-information.component.ts
new file mode 100644
index 0000000..fea4c44
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/model-information/model-information.component.ts
@@ -0,0 +1,42 @@
+import {Component, Input} from '@angular/core';
+import * as _ from 'lodash';
+
+@Component({
+  selector: 'model-information',
+  templateUrl: 'model-information.html',
+  styleUrls: ['model-information.scss']
+})
+
+export class ModelInformationComponent {
+  private _modelInformationItems: Array<ModelInformationItem>;
+
+
+  get modelInformationItems(): Array<ModelInformationItem> {
+    return this._modelInformationItems;
+  }
+
+  @Input()
+  set modelInformationItems(_modelInformationItems: Array<ModelInformationItem>) {
+    if (_modelInformationItems) {
+      this._modelInformationItems = _modelInformationItems.filter(x => x.mandatory || (!_.isEmpty(x.values) && !_.isEmpty(x.values[0])));
+    }
+  }
+}
+
+
+export class ModelInformationItem {
+  label: string;
+  testsId: string;
+  values: Array<string>;
+  toolTipText: string;
+  mandatory: boolean;
+
+  constructor(label: string, testsId: string, values: Array<any>, toolTipText: string = "", mandatory: boolean = false,nested:boolean=false) {
+    this.label = label;
+    this.testsId = testsId;
+    this.values = values;
+    this.toolTipText = toolTipText;
+    this.mandatory = mandatory;
+  }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/model-information/model-information.html b/vid-webpack-master/src/app/shared/components/model-information/model-information.html
new file mode 100644
index 0000000..456dfde
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/model-information/model-information.html
@@ -0,0 +1,12 @@
+<div id="model-information">
+  <div *ngFor="let item of modelInformationItems" class="item" attr.data-tests-id="model-item-{{item.label}}">
+    <tooltip-content #a>
+      <span> {{item.toolTipText}}</span>
+    </tooltip-content>
+
+    <div class="wrapper" [tooltip]="a" [tooltipDisabled]="!item.toolTipText" tooltipPlacement="top" [tooltipAnimation]="false">
+      <label attr.data-tests-id="model-item-label-{{item.testsId}}">{{item.label}}</label>
+      <div *ngFor="let value of item.values" attr.data-tests-id="model-item-value-{{item.testsId}}">{{value}}</div>
+    </div>
+  </div>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/model-information/model-information.scss b/vid-webpack-master/src/app/shared/components/model-information/model-information.scss
new file mode 100644
index 0000000..cd42136
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/model-information/model-information.scss
@@ -0,0 +1,34 @@
+#model-information {
+  overflow: auto;
+
+}
+
+tooltip-content span {
+  font-family: OpenSans-Regular;
+  font-size: 12px;
+  color: #FFFFFF;
+  letter-spacing: 0;
+  line-height: 16px;
+}
+
+.item {
+  display: block;
+
+  .wrapper {
+
+    display: inline-block;
+    margin-bottom: 25px;
+
+    label {
+      font-family: OpenSans-Semibold;
+      font-size: 12px;
+    }
+
+    div {
+      font-family: OpenSans-Regular;
+      font-size: 14px;
+    }
+  }
+}
+
+
diff --git a/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.html b/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.html
new file mode 100644
index 0000000..bbe7bc7
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.html
@@ -0,0 +1,5 @@
+<div class="width-100">
+  <div class="text-title" [ngClass]="titleClass">{{title}}</div>
+  <div class="text-subtitle" [ngClass]="subtitleClass">{{subtitle}}</div>
+  <img  id="not-node-img-id" src="{{iconPath}}" alt="" class="no-content-icon" [ngClass]="iconClass" data-tests-id="no-content-icon">
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.scss b/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.scss
new file mode 100644
index 0000000..1320ef7
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.scss
@@ -0,0 +1,26 @@
+.width-100 {
+  width: 100%;
+  margin-top: 126px;
+
+}
+
+.text-title {
+  font-family: OpenSans-Semibold;
+  font-size: 16px;
+  color: #4A4A4A;
+  text-align: center;
+}
+
+.text-subtitle {
+  font-family: OpenSans-Regular;
+  font-size: 16px;
+  color: #959595;
+  text-align: center;
+  margin-top: 7px;
+}
+
+.no-content-icon {
+  display: block;
+  vertical-align: middle;
+  margin: 30px auto;
+}
diff --git a/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.ts b/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.ts
new file mode 100644
index 0000000..7f4e982
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/no-content-message-and-icon/no-content-message-and-icon.component.ts
@@ -0,0 +1,23 @@
+import {Component, Input} from '@angular/core';
+
+@Component({
+  selector: 'no-content-message-and-icon',
+  templateUrl: './no-content-message-and-icon.component.html',
+  styleUrls: ['./no-content-message-and-icon.component.scss']
+})
+
+
+export class NoContentMessageAndIconComponent {
+  constructor() {}
+
+  @Input() title: string;
+  @Input() subtitle: string;
+  @Input() iconPath: string;
+
+  @Input() titleClass: string="";
+  @Input() subtitleClass: string="";
+  @Input() iconClass: string="";
+
+}
+
+
diff --git a/vid-webpack-master/src/app/shared/components/popover/popover.component.html b/vid-webpack-master/src/app/shared/components/popover/popover.component.html
new file mode 100644
index 0000000..c551559
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/popover/popover.component.html
@@ -0,0 +1,8 @@
+<div
+  triggers="mouseenter:mouseleave"
+  popover="{{value}}"
+  [hidden]="value == null"
+  container="body">
+  <ng-content ></ng-content>
+</div>
+
diff --git a/vid-webpack-master/src/app/shared/components/popover/popover.component.scss b/vid-webpack-master/src/app/shared/components/popover/popover.component.scss
new file mode 100644
index 0000000..ca2800a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/popover/popover.component.scss
@@ -0,0 +1,4 @@
+.popover.popover-top.top {
+  color : green !important;
+  font-size: 10px;
+}
diff --git a/vid-webpack-master/src/app/shared/components/popover/popover.component.ts b/vid-webpack-master/src/app/shared/components/popover/popover.component.ts
new file mode 100644
index 0000000..d6a4c3a
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/popover/popover.component.ts
@@ -0,0 +1,17 @@
+import {Component, Input} from "@angular/core";
+
+@Component({
+  selector: 'custom-popover',
+  templateUrl: 'popover.component.html',
+  styles: [`
+        :host >>> .popover {
+          font-size: 13px;
+          text-align: left;
+          z-index: 10000;
+        }
+    `]
+})
+
+export class PopoverComponent {
+  @Input() value: String;
+}
diff --git a/vid-webpack-master/src/app/shared/components/spinner/spinner.component.html b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.html
new file mode 100644
index 0000000..cb11fee
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.html
@@ -0,0 +1,2 @@
+<div *ngIf="show"
+     class="spinner"></div>
diff --git a/vid-webpack-master/src/app/shared/components/spinner/spinner.component.scss b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.scss
new file mode 100644
index 0000000..d31dfed
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.scss
@@ -0,0 +1,87 @@
+.spinner {
+  height: 150px;
+  width: 150px;
+  margin: 0 auto;
+  -webkit-animation: rotation .6s infinite linear;
+  animation: rotation .6s infinite linear;
+  border: 6px solid rgba(0, 174, 239, 0.01);
+  border-radius: 100%;
+  position: absolute;
+  z-index: 1000;
+  left: 50%;
+  right: 50%;
+  top: 50%;
+  bottom: 50%;
+}
+
+
+
+.spinner:before {
+  content: "";
+  display: block;
+  position: absolute;
+  top: -6px;
+  height: 100%;
+  width: 100%;
+  border-top: 6px solid #009fdb;
+  border-left: 6px solid transparent;
+  border-bottom: 6px solid #c3161600;
+  border-right: 6px solid transparent;
+  border-radius: 100%;
+}
+
+@-webkit-keyframes rotation {
+  from {-webkit-transform: rotate(0deg);}
+  to {-webkit-transform: rotate(359deg);}
+}
+@-moz-keyframes rotation {
+  from {-moz-transform: rotate(0deg);}
+  to {-moz-transform: rotate(359deg);}
+}
+@-o-keyframes rotation {
+  from {-o-transform: rotate(0deg);}
+  to {-o-transform: rotate(359deg);}
+}
+@keyframes rotation {
+  from {transform: rotate(0deg);}
+  to {transform: rotate(359deg);}
+}
+
+.spinner-sm {
+  height:16px;
+  width:16px;
+}
+
+.spinner-md {
+  height:40px;
+  width:40px;
+}
+
+.spinner-lr {
+  height:150px;
+  width:150px;
+}
+
+.spinner-red {
+  border:6px solid rgba(216, 27, 34, .15);
+}
+
+.spinner-red:before {
+  border-top:6px solid rgba(216, 27, 34, 1);
+}
+
+.spinner-green {
+  border:6px solid rgba(40, 183, 121, .15);
+}
+
+.spinner-green:before {
+  border-top:6px solid rgba(40, 183, 121, 1);
+}
+
+.spinner-grey {
+  border:6px solid rgba(139, 146, 154, .15);
+}
+
+.spinner-grey:before {
+  border-top:6px solid rgba(139, 146, 154, 1);
+}
diff --git a/vid-webpack-master/src/app/shared/components/spinner/spinner.component.spec.ts b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.spec.ts
new file mode 100644
index 0000000..531ee8c
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.spec.ts
@@ -0,0 +1,42 @@
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {HttpClientTestingModule} from '@angular/common/http/testing';
+import { SpinnerComponent } from './spinner.component';
+
+describe('Spinner component', () => {
+  let component: SpinnerComponent;
+  let fixture: ComponentFixture<SpinnerComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      imports: [HttpClientTestingModule],
+      providers: [],
+      declarations: [SpinnerComponent ]
+    })
+      .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SpinnerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('component should be defined', () => {
+    expect(component).toBeDefined();
+  });
+
+
+  it('component constructor should subscribe of showSpinner event with true', ()=> {
+    SpinnerComponent.showSpinner.next(true);
+    expect(component.show).toBeTruthy();
+  });
+
+  it('component constructor should subscribe of showSpinner event with false', ()=> {
+    SpinnerComponent.showSpinner.next(false);
+    expect(component.show).toBeFalsy();
+  });
+
+
+
+
+});
diff --git a/vid-webpack-master/src/app/shared/components/spinner/spinner.component.ts b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.ts
new file mode 100644
index 0000000..0ce5d20
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/spinner/spinner.component.ts
@@ -0,0 +1,18 @@
+import { Component, Input } from '@angular/core';
+import { Subject } from 'rxjs/Subject';
+
+@Component({
+  selector : 'spinner-component',
+  templateUrl : './spinner.component.html',
+  styleUrls : ['./spinner.component.scss']
+})
+export class SpinnerComponent {
+  show : boolean = false;
+  static showSpinner: Subject<boolean> = new Subject<boolean>();
+
+  constructor(){
+    SpinnerComponent.showSpinner.subscribe((status) => {
+      this.show = status;
+    })
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator.spec.ts b/vid-webpack-master/src/app/shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator.spec.ts
new file mode 100644
index 0000000..ec9f3f7
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator.spec.ts
@@ -0,0 +1,39 @@
+import { ReflectiveInjector } from '@angular/core';
+import { NumbersLettersUnderscoreValidator } from './numbersLettersUnderscore.validator';
+
+describe('Numbers letters underscore validator', () => {
+  let injector;
+  let service: NumbersLettersUnderscoreValidator;
+
+  beforeEach(() => {
+
+    let injector = ReflectiveInjector.resolveAndCreate([
+      NumbersLettersUnderscoreValidator
+    ]);
+
+    service = injector.get(NumbersLettersUnderscoreValidator);
+  });
+
+
+  describe('#valid', () => {
+    it("'legal' should return null", ()=> {
+      let legalVal: string = "legal";
+      let result = NumbersLettersUnderscoreValidator.valid(legalVal);
+      expect(result).toBeNull();
+    });
+
+    it("'illegal' should return object with invalidNumberLettersUnderscore true", ()=> {
+      let illegalVal: string = "illegal-Val";
+      let result = NumbersLettersUnderscoreValidator.valid(illegalVal);
+      expect(result.invalidNumberLettersUnderscore).toBeTruthy();
+    });
+
+    it("'null' should return null", ()=> {
+      let nullVal: string = null
+      let result = NumbersLettersUnderscoreValidator.valid(nullVal);
+      expect(result).toBeNull();
+    });
+
+
+  });
+});
diff --git a/vid-webpack-master/src/app/shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator.ts b/vid-webpack-master/src/app/shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator.ts
new file mode 100644
index 0000000..418bdfc
--- /dev/null
+++ b/vid-webpack-master/src/app/shared/components/validators/numbersLettersUnderscore/numbersLettersUnderscore.validator.ts
@@ -0,0 +1,20 @@
+import { Injectable } from '@angular/core';
+import { isNullOrUndefined, isString } from 'util';
+
+@Injectable()
+export class NumbersLettersUnderscoreValidator {
+  static valid(control: any) {
+    let reg =  /^[a-zA-Z0-9_]*$/;
+
+    if(isNullOrUndefined(control)) return null;
+    let val = isString(control) ? control : control.value;
+    if (val === null) {
+      return {'invalidNumberLettersUnderscore': true};
+    }
+    if (reg.test(val)) {
+      return null;
+    } else {
+      return {'invalidNumberLettersUnderscore': true};
+    }
+  }
+}