diff options
author | Israel Lavi <il0695@att.com> | 2018-08-07 10:54:17 +0300 |
---|---|---|
committer | Israel Lavi <il0695@att.com> | 2018-08-07 11:06:44 +0300 |
commit | b2a3acea0d0f66028c9ce5fad02d4ecc64abf70c (patch) | |
tree | 8d70110f34cb845965c42a5915e950bca967d2c3 /src/angular | |
parent | 05b37297177e8a342668c15e5d6f738b51f7aedd (diff) |
Initial commit.
Adding files needed for Linux Foundation.
Change-Id: I9f2b4851a5ae01f83800c7f8bab8608a2221c730
Issue-ID: SDC-1608
Signed-off-by: Israel Lavi <il0695@att.com>
Diffstat (limited to 'src/angular')
101 files changed, 1056 insertions, 460 deletions
diff --git a/src/angular/accordion/accordion.component.html.ts b/src/angular/accordion/accordion.component.html.ts index ac5f81f..2679906 100644 --- a/src/angular/accordion/accordion.component.html.ts +++ b/src/angular/accordion/accordion.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="sdc-accordion" [ngClass]="customCSSClass"> <div class="sdc-accordion-header" (click)="toggleAccordion()" [ngClass]="{'arrow-right': arrowDirection === accordionArrowDirection.right}"> <div class="svg-icon-wrapper bottom" [ngClass]="{'down': open}"> diff --git a/src/angular/accordion/accordion.component.ts b/src/angular/accordion/accordion.component.ts index b16df89..e81597e 100644 --- a/src/angular/accordion/accordion.component.ts +++ b/src/angular/accordion/accordion.component.ts @@ -1,10 +1,6 @@ -/** - * Created by M.S.BIT on 26/04/2018. - */ - -import {Component, Input, Output, EventEmitter} from "@angular/core"; -import {Placement} from "../common/enums"; -import template from './accordion.component.html'; +import { Component, Input, Output, EventEmitter } from "@angular/core"; +import { Placement } from "../common/enums"; +import { template } from './accordion.component.html'; @Component({ selector: 'sdc-accordion', diff --git a/src/angular/accordion/accordion.module.ts b/src/angular/accordion/accordion.module.ts index 6cda646..7b3bb95 100644 --- a/src/angular/accordion/accordion.module.ts +++ b/src/angular/accordion/accordion.module.ts @@ -1,10 +1,7 @@ -/** - * Created by M.S.BIT on 26/04/2018. - */ import { NgModule } from "@angular/core"; import { CommonModule } from "@angular/common"; -import {AccordionComponent} from "./accordion.component"; -import {SvgIconModule} from "../svg-icon/svg-icon.module"; +import { AccordionComponent } from "./accordion.component"; +import { SvgIconModule } from "../svg-icon/svg-icon.module"; @NgModule({ declarations: [ diff --git a/src/angular/autocomplete/autocomplete.component.html.ts b/src/angular/autocomplete/autocomplete.component.html.ts index 5df7352..8e57f9e 100644 --- a/src/angular/autocomplete/autocomplete.component.html.ts +++ b/src/angular/autocomplete/autocomplete.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="sdc-autocomplete-container" [ngClass]="{'results-shown': autoCompleteResults.length}"> <sdc-filter-bar [placeholder]="placeholder" diff --git a/src/angular/autocomplete/autocomplete.component.ts b/src/angular/autocomplete/autocomplete.component.ts index 5570eff..45718b2 100644 --- a/src/angular/autocomplete/autocomplete.component.ts +++ b/src/angular/autocomplete/autocomplete.component.ts @@ -1,15 +1,10 @@ -import { OnInit, animate, Component, EventEmitter, Input, Output, state, style, transition, trigger } from '@angular/core'; -import { FilterBarComponent } from "../filterbar/filter-bar.component"; -import { URLSearchParams, Http } from "@angular/http"; +import { OnInit, Component, EventEmitter, Input, Output } from '@angular/core'; +import { animate, state, style, transition, trigger } from '@angular/animations'; import { AutocompletePipe } from "./autocomplete.pipe"; -import template from "./autocomplete.component.html"; +import { template } from "./autocomplete.component.html"; +import { HttpClient, HttpParams } from '@angular/common/http'; import 'rxjs/add/operator/map'; -export interface IDataSchema { - key: string; - value: string; -} - @Component({ selector: 'sdc-autocomplete', template: template, @@ -25,10 +20,9 @@ export interface IDataSchema { })), transition('* => *', animate('200ms')) ]), - ], - providers: [AutocompletePipe] + ] }) -export class SearchWithAutoCompleteComponent implements OnInit { +export class AutoCompleteComponent implements OnInit { @Input() public data: any[] = []; @Input() public dataSchema: IDataSchema; @Input() public dataUrl: string; @@ -36,12 +30,12 @@ export class SearchWithAutoCompleteComponent implements OnInit { @Input() public placeholder: string; @Output() public itemSelected: EventEmitter<any> = new EventEmitter<any>(); - private searchQuery: string; + public searchQuery: string; private complexData: any[] = []; - private autoCompleteResults: any[] = []; + public autoCompleteResults: any[] = []; private isItemSelected: boolean = false; - public constructor(private http: Http, private autocompletePipe: AutocompletePipe) { + public constructor(private http: HttpClient, private autocompletePipe: AutocompletePipe) { } public ngOnInit(): void { @@ -82,18 +76,18 @@ export class SearchWithAutoCompleteComponent implements OnInit { this.itemSelected.emit(selectedItem.key); } - private onSearchQueryChanged = (searchText: string): void => { + public onSearchQueryChanged = (searchText: string): void => { if (searchText !== this.searchQuery) { this.searchQuery = searchText; if (!this.searchQuery) { this.onClearSearch(); } else { if (this.dataUrl) { - const params: URLSearchParams = new URLSearchParams(); - params.set('searchQuery', this.searchQuery); - this.http.get(this.dataUrl, {search: params}) + const params = new HttpParams(); + params.append('searchQuery', this.searchQuery); + this.http.get(this.dataUrl, {params}) .map((response) => { - this.data = response.json(); + this.data = JSON.parse(JSON.stringify(response)); this.handleLocalData(); this.autoCompleteResults = this.complexData; }).subscribe(); @@ -112,3 +106,8 @@ export class SearchWithAutoCompleteComponent implements OnInit { } } } + +export interface IDataSchema { + key: string; + value: string; +} diff --git a/src/angular/autocomplete/autocomplete.module.ts b/src/angular/autocomplete/autocomplete.module.ts index 1bead47..f105669 100644 --- a/src/angular/autocomplete/autocomplete.module.ts +++ b/src/angular/autocomplete/autocomplete.module.ts @@ -1,23 +1,26 @@ import { NgModule } from "@angular/core"; -import { SearchWithAutoCompleteComponent } from "./autocomplete.component"; +import { AutoCompleteComponent } from "./autocomplete.component"; import { CommonModule } from "@angular/common"; import { FilterBarModule } from "../filterbar/filter-bar.module"; import { AutocompletePipe } from "./autocomplete.pipe"; -import { HttpModule } from '@angular/http'; +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ declarations: [ - SearchWithAutoCompleteComponent, + AutoCompleteComponent, AutocompletePipe ], imports: [ + BrowserModule, + BrowserAnimationsModule, FilterBarModule, - CommonModule, - HttpModule + CommonModule ], exports: [ - SearchWithAutoCompleteComponent - ], + AutoCompleteComponent, + AutocompletePipe + ] }) export class AutoCompleteModule { } diff --git a/src/angular/buttons/button-file-opener.component.html.ts b/src/angular/buttons/button-file-opener.component.html.ts new file mode 100644 index 0000000..dd24be3 --- /dev/null +++ b/src/angular/buttons/button-file-opener.component.html.ts @@ -0,0 +1,18 @@ +export const template = ` +<div (click)="fileOpener.click()" + class="sdc-button sdc-button__{{ type }} btn-{{ size }} {{ iconPositionClass }}" + [attr.data-tests-id]="testId" + > + {{ text }} + <input + #fileOpener + type="file" + [accept]="allowedExtensions" + [disabled] = "disabled" + (change)="onFileSelect($event)" + base-sixty-four-input + /> +</div> +`; + +// base-sixty-four-input diff --git a/src/angular/buttons/button-file-opener.component.ts b/src/angular/buttons/button-file-opener.component.ts new file mode 100644 index 0000000..399eb9a --- /dev/null +++ b/src/angular/buttons/button-file-opener.component.ts @@ -0,0 +1,61 @@ +import { Component, Input, Output, EventEmitter, HostBinding, ViewChild, AfterViewInit } from '@angular/core'; +import { ButtonComponent } from './button.component'; +import { template } from "./button-file-opener.component.html"; + +export class FileObject { + filesize: string; + filetype: string; + filename: string; + base64: string; +} + +@Component({ + selector: "sdc-button-file-opener", + template: template, + styles: [` + input[type=file] { + display: none; + } + `] +}) +export class ButtonFileOpenerComponent extends ButtonComponent implements AfterViewInit { + + @Input() public extensions: string; + @Output() public fileUpload: EventEmitter<any>; + @HostBinding('class.sdc-button__wrapper') true; + + public allowedExtensions: string; + private fileObject: FileObject; + + constructor() { + super(); + this.fileUpload = new EventEmitter<any>(); + this.fileObject = new FileObject(); + } + + ngAfterViewInit() : void { + this.allowedExtensions = this.extensions && this.extensions.split(',').map(x => '.' + x).join(','); + } + + public onFileSelectaa(event): void { + let file = event.srcElement.files[0]; + debugger + this.fileUpload.emit({file: file}); + } + + public onFileSelect(e): void { + var file = e.dataTransfer ? e.dataTransfer.files[0] : e.target.files[0]; + var reader = new FileReader(); + this.fileObject.filesize = file.size; + this.fileObject.filetype = file.type; + this.fileObject.filename = file.name; + reader.onload = this._handleReaderLoaded.bind(this); + reader.readAsDataURL(file); + } + private _handleReaderLoaded(e) { + let base64 = e.target.result; + this.fileObject.base64 = base64.split('base64,')[1]; + this.fileUpload.emit(this.fileObject); + } + +} diff --git a/src/angular/buttons/button.component.html.ts b/src/angular/buttons/button.component.html.ts index f903fd1..33a630a 100644 --- a/src/angular/buttons/button.component.html.ts +++ b/src/angular/buttons/button.component.html.ts @@ -1,11 +1,11 @@ -export default ` +export const template = ` <button class="sdc-button sdc-button__{{ type }} btn-{{ size }} {{ iconPositionClass }}" [disabled] = "disabled || show_spinner" [attr.data-tests-id]="testId"> <svg-icon *ngIf="icon_name" [name]="icon_name" - [mode]="iconMode" + [mode]="type" [size]="'medium'" > </svg-icon> diff --git a/src/angular/buttons/button.component.ts b/src/angular/buttons/button.component.ts index 1f049dc..d57c5f1 100644 --- a/src/angular/buttons/button.component.ts +++ b/src/angular/buttons/button.component.ts @@ -1,16 +1,17 @@ import { Component, HostBinding, Input, OnInit } from "@angular/core"; -import { Placement } from "../common/enums"; -import template from "./button.component.html"; +import { Placement, ButtonType } from "../common/enums"; +import { IButtonComponent } from './ibutton.interface'; +import { template } from "./button.component.html"; @Component({ selector: "sdc-button", template: template }) -export class ButtonComponent implements OnInit { +export class ButtonComponent implements OnInit, IButtonComponent { @Input() public text: string; @Input() public disabled: boolean; - @Input() public type: string; + @Input() public type: ButtonType; @Input() public size: string; @Input() public preventDoubleClick: boolean; @Input() public icon_name: string; @@ -21,21 +22,18 @@ export class ButtonComponent implements OnInit { public placement = Placement; private lastClick: Date; - private iconPositionClass: string; - private iconMode: string; + public iconPositionClass: string; @HostBinding('class.sdc-button__wrapper') true; constructor() { - this.type = "primary"; + this.type = ButtonType.primary; this.size = "default"; this.disabled = false; - this.iconMode = 'primary'; } public ngOnInit(): void { this.iconPositionClass = this.icon_position ? 'sdc-icon-' + this.icon_position : ''; - this.iconMode = (this.type === "primary") ? 'info' : 'primary'; } public onClick = (e): void => { diff --git a/src/angular/buttons/buttons.module.ts b/src/angular/buttons/buttons.module.ts index c804758..5c6bdc8 100644 --- a/src/angular/buttons/buttons.module.ts +++ b/src/angular/buttons/buttons.module.ts @@ -2,18 +2,20 @@ import { NgModule } from "@angular/core"; import { ButtonComponent } from "./button.component"; import { CommonModule } from "@angular/common"; import { SvgIconModule } from './../svg-icon/svg-icon.module'; +import { ButtonFileOpenerComponent } from './button-file-opener.component'; @NgModule({ declarations: [ - ButtonComponent + ButtonComponent, + ButtonFileOpenerComponent ], imports: [ CommonModule, SvgIconModule ], exports: [ - ButtonComponent - + ButtonComponent, + ButtonFileOpenerComponent ], }) export class ButtonsModule { diff --git a/src/angular/buttons/ibutton.interface.ts b/src/angular/buttons/ibutton.interface.ts new file mode 100644 index 0000000..289935b --- /dev/null +++ b/src/angular/buttons/ibutton.interface.ts @@ -0,0 +1,14 @@ +import { Placement, ButtonType } from "../common/enums"; + +export interface IButtonComponent { + text: string; + disabled?: boolean; + type?: ButtonType; + testId?: string; + preventDoubleClick?: boolean; + icon_name?: string; + icon_position?: string; + show_spinner?: boolean; + spinner_position?: Placement; + size?: string; +} diff --git a/src/angular/checklist/checklist.component.html.ts b/src/angular/checklist/checklist.component.html.ts index cb6f540..c48d8eb 100644 --- a/src/angular/checklist/checklist.component.html.ts +++ b/src/angular/checklist/checklist.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div *ngFor="let checkbox of checklistModel.checkboxes" #currentCheckbox> <div class="checkbox-item"> <sdc-checkbox [label]="checkbox.label" diff --git a/src/angular/checklist/checklist.component.ts b/src/angular/checklist/checklist.component.ts index 386cd3e..b512378 100644 --- a/src/angular/checklist/checklist.component.ts +++ b/src/angular/checklist/checklist.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; import { ChecklistModel } from "./models/Checklist"; import { ChecklistItemModel } from "./models/ChecklistItem"; -import template from "./checklist.component.html"; +import { template } from "./checklist.component.html"; @Component({ selector: 'sdc-checklist', @@ -15,7 +15,7 @@ export class ChecklistComponent { // push/pop the checkbox value if (checkbox.isChecked) { currentChecklistModel.selectedValues.push(checkbox.value); - }else { + } else { const index: number = currentChecklistModel.selectedValues.indexOf(checkbox.value); currentChecklistModel.selectedValues.splice(index, 1); } diff --git a/src/angular/checklist/models/ChecklistItem.ts b/src/angular/checklist/models/ChecklistItem.ts index e2d812a..7b1b321 100644 --- a/src/angular/checklist/models/ChecklistItem.ts +++ b/src/angular/checklist/models/ChecklistItem.ts @@ -6,11 +6,13 @@ export class ChecklistItemModel { public value: any; public disabled: boolean; public isChecked: boolean; + public testId: string; public subLevelChecklist: ChecklistModel; - constructor(label: string, disabled?: boolean, isChecked?: boolean, subLevelChecklist?: ChecklistModel, value?: any) { + constructor(label: string, disabled?: boolean, isChecked?: boolean, subLevelChecklist?: ChecklistModel, testId?: string, value?: any) { this.label = label; this.disabled = disabled; this.isChecked = isChecked; + this.testId = testId; this.value = isUndefined(value) ? label : value; this.subLevelChecklist = subLevelChecklist; } diff --git a/src/angular/common/enums.ts b/src/angular/common/enums.ts index 0825d2f..07c1a2b 100644 --- a/src/angular/common/enums.ts +++ b/src/angular/common/enums.ts @@ -12,12 +12,37 @@ export enum Size { x_small = 'x_small' } +export enum BackgroundShape { + circle = 'circle', + rectangle = 'rectangle' +} + +export enum BackgroundColor { + primary = 'primary', + secondary = 'secondary', + success = 'success', + error = 'error', + warning = 'warning', + info = 'info' +} + +// TODO: Replace this with type export enum Mode { primary = 'primary', secondary = 'secondary', success = 'success', error = 'error', warning = 'warning', + info = 'info', + white = 'white' +} + +export enum ButtonType { + primary = 'primary', + secondary = 'secondary', + success = 'success', + error = 'error', + warning = 'warning', info = 'info' } diff --git a/src/angular/common/index.ts b/src/angular/common/index.ts index 839eba9..81d39b1 100644 --- a/src/angular/common/index.ts +++ b/src/angular/common/index.ts @@ -1,3 +1,4 @@ -import * as SdcUiCommon from './enums'; - -export { SdcUiCommon }; +export * from './enums'; +export * from '../modals/models/modal-config'; +export * from '../checklist/models/Checklist'; +export * from '../checklist/models/ChecklistItem'; diff --git a/src/angular/components.ts b/src/angular/components.ts index 8e06197..006bdf7 100644 --- a/src/angular/components.ts +++ b/src/angular/components.ts @@ -1,25 +1,25 @@ /* - Exports all the components and services of sdc-ui. + Exports all the components of onap-ui-angular. */ // Form Elements -export { InputComponent } from "./form-elements/input/input.component"; +export { InputComponent } from "./form-elements/text-elements/input/input.component"; export { DropDownComponent } from "./form-elements/dropdown/dropdown.component"; export { CheckboxComponent } from "./form-elements/checkbox/checkbox.component"; export { RadioGroupComponent } from "./form-elements/radios/radio-buttons-group.component"; +export { TextareaComponent } from "./form-elements/text-elements/textarea/textarea.component"; // Buttons export { ButtonComponent } from "./buttons/button.component"; +export { ButtonFileOpenerComponent } from "./buttons/button-file-opener.component"; // Modals export { ModalComponent } from "./modals/modal.component"; -export { ModalService } from "./modals/modal.service"; export { ModalButtonComponent } from "./modals/modal-button.component"; // Notifications export { NotificationComponent } from "./notifications/notification/notification.component"; export { NotificationContainerComponent } from "./notifications/container/notifcontainer.component"; -export { NotificationsService } from "./notifications/services/notifications.service"; // Popup Menu export { PopupMenuListComponent } from "./popup-menu/popup-menu-list.component"; @@ -48,3 +48,25 @@ export { SvgIconLabelComponent } from "./svg-icon/svg-icon-label.component"; // Accordion export { AccordionComponent } from './accordion/accordion.component'; + +// Multiline Ellipsis +export { MultilineEllipsisComponent } from './multiline-ellipsis/multiline-ellipsis.component'; + +// AutoComplete +export { AutoCompleteComponent } from './autocomplete/autocomplete.component'; +export { AutocompletePipe } from './autocomplete/autocomplete.pipe'; + +// Filter +export { FilterBarComponent } from './filterbar/filter-bar.component'; + +// Infinite Scroll +export { InfiniteScrollDirective } from './infinite-scroll/infinite-scroll.directive'; + +// Loader +export { LoaderComponent } from './loader/loader.component'; + +// Searchbar +export { SearchBarComponent } from './searchbar/search-bar.component'; + +// Tooltip +export { TooltipDirective } from "./tooltip/tooltip.directive"; diff --git a/src/angular/favicon.ico b/src/angular/favicon.ico Binary files differnew file mode 100644 index 0000000..8081c7c --- /dev/null +++ b/src/angular/favicon.ico diff --git a/src/angular/filterbar/filter-bar.component.html.ts b/src/angular/filterbar/filter-bar.component.html.ts index a7d55e2..ca1c837 100644 --- a/src/angular/filterbar/filter-bar.component.html.ts +++ b/src/angular/filterbar/filter-bar.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="search-bar-container"> <sdc-input class="search-bar-input" [label]="label" diff --git a/src/angular/filterbar/filter-bar.component.ts b/src/angular/filterbar/filter-bar.component.ts index 49cc154..fa3eac4 100644 --- a/src/angular/filterbar/filter-bar.component.ts +++ b/src/angular/filterbar/filter-bar.component.ts @@ -1,5 +1,5 @@ import { Component, Input, Output, EventEmitter, HostBinding } from '@angular/core'; -import template from "./filter-bar.component.html"; +import { template } from "./filter-bar.component.html"; @Component({ selector: 'sdc-filter-bar', @@ -12,7 +12,6 @@ export class FilterBarComponent { @Input() public placeholder: string; @Input() public label: string; @Input() public debounceTime: number; - @Input() public searchQuery: string; @Output() public searchQueryChange: EventEmitter<any> = new EventEmitter<any>(); @@ -20,7 +19,7 @@ export class FilterBarComponent { this.debounceTime = 200; } - private searchTextChange = ($event): void => { + public searchTextChange = ($event): void => { this.searchQueryChange.emit($event); } diff --git a/src/angular/filterbar/filter-bar.module.ts b/src/angular/filterbar/filter-bar.module.ts index c3604ed..f03caed 100644 --- a/src/angular/filterbar/filter-bar.module.ts +++ b/src/angular/filterbar/filter-bar.module.ts @@ -7,8 +7,10 @@ import { FormElementsModule } from "../form-elements/form-elements.module"; declarations: [ FilterBarComponent ], - imports: [CommonModule, - FormElementsModule], + imports: [ + CommonModule, + FormElementsModule + ], exports: [ FilterBarComponent ], diff --git a/src/angular/form-elements/checkbox/checkbox.component.html.ts b/src/angular/form-elements/checkbox/checkbox.component.html.ts index f4031db..3fdd53f 100644 --- a/src/angular/form-elements/checkbox/checkbox.component.html.ts +++ b/src/angular/form-elements/checkbox/checkbox.component.html.ts @@ -1,7 +1,7 @@ -export default ` +export const template = ` <div class="sdc-checkbox"> <label SdcRippleClickAnimation [rippleClickDisabled]="disabled"> - <input type="checkbox" class="sdc-checkbox__input" [ngModel]="checked" (ngModelChange)="toggleState($event)" [disabled]="disabled"> + <input type="checkbox" class="sdc-checkbox__input" [ngModel]="checked" (ngModelChange)="toggleState($event)" [disabled]="disabled" [attr.data-tests-id]="testId"> <span class="sdc-checkbox__label">{{ label }}</span> </label> </div> diff --git a/src/angular/form-elements/checkbox/checkbox.component.spec.ts b/src/angular/form-elements/checkbox/checkbox.component.spec.ts index 36f478e..8fc63e2 100644 --- a/src/angular/form-elements/checkbox/checkbox.component.spec.ts +++ b/src/angular/form-elements/checkbox/checkbox.component.spec.ts @@ -3,7 +3,6 @@ import { CheckboxComponent } from "./checkbox.component"; import { AnimationDirectivesModule } from "../../animations/animation-directives.module"; import { FormsModule } from "@angular/forms"; - describe("Checbox Tests", ()=>{ let component: CheckboxComponent; beforeEach(async(() => { diff --git a/src/angular/form-elements/checkbox/checkbox.component.ts b/src/angular/form-elements/checkbox/checkbox.component.ts index ec05eac..2b50e6d 100644 --- a/src/angular/form-elements/checkbox/checkbox.component.ts +++ b/src/angular/form-elements/checkbox/checkbox.component.ts @@ -1,5 +1,5 @@ import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; -import template from "./checkbox.component.html"; +import { template } from "./checkbox.component.html"; @Component({ selector: 'sdc-checkbox', @@ -10,6 +10,7 @@ export class CheckboxComponent { @Input() label:string; @Input() checked:boolean; @Input() disabled:boolean; + @Input() testId: string; @Output() checkedChange:EventEmitter<any> = new EventEmitter<any>(); public toggleState(newState:boolean) { diff --git a/src/angular/form-elements/dropdown/dropdown-models.ts b/src/angular/form-elements/dropdown/dropdown-models.ts index fa8dc23..a718c07 100644 --- a/src/angular/form-elements/dropdown/dropdown-models.ts +++ b/src/angular/form-elements/dropdown/dropdown-models.ts @@ -1,14 +1,14 @@ export enum DropDownTypes { - Regular, - Headless, - Auto + Regular = "Regular", + Headless = "Headless", + Auto = "Auto" } export enum DropDownOptionType { - Simple, // default - Header, - Disable, - HorizontalLine + Simple = "Simple", // default + Header = "Header", + Disable = "Disable", + HorizontalLine = "HorizontalLine" } export interface IDropDownOption { diff --git a/src/angular/form-elements/dropdown/dropdown.component.html.ts b/src/angular/form-elements/dropdown/dropdown.component.html.ts index a4247a4..36ce17c 100644 --- a/src/angular/form-elements/dropdown/dropdown.component.html.ts +++ b/src/angular/form-elements/dropdown/dropdown.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="sdc-dropdown" #dropDownWrapper [ngClass]="{ 'headless': type === cIDropDownTypes.Headless, diff --git a/src/angular/form-elements/dropdown/dropdown.component.ts b/src/angular/form-elements/dropdown/dropdown.component.ts index a23072f..33f54ac 100644 --- a/src/angular/form-elements/dropdown/dropdown.component.ts +++ b/src/angular/form-elements/dropdown/dropdown.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Input, Output, forwardRef, OnChanges, SimpleChanges, OnInit, ElementRef, ViewChild, AfterViewInit, HostListener, Renderer } from '@angular/core'; import { IDropDownOption, DropDownOptionType, DropDownTypes } from "./dropdown-models"; import { ValidatableComponent } from './../validation/validatable.component'; -import template from './dropdown.component.html'; +import { template } from './dropdown.component.html'; @Component({ selector: 'sdc-dropdown', @@ -24,7 +24,7 @@ export class DropDownComponent extends ValidatableComponent implements OnChanges this.onClickDocument(e); } - private bottomVisible = true; + public bottomVisible = true; private myRenderer: Renderer; // Drop-down show/hide flag. default is false (closed) @@ -57,7 +57,9 @@ export class DropDownComponent extends ValidatableComponent implements OnChanges ngOnInit(): void { if (this.options) { this.allOptions = this.options; - if (this.options.find(option => option.type === DropDownOptionType.Header)) { + // To support ES5 + if (this.options.filter(option => option.type === DropDownOptionType.Header).length>0) { + // if (this.options.find(option => option.type === DropDownOptionType.Header)) { this.isGroupDesign = true; } } @@ -114,14 +116,20 @@ export class DropDownComponent extends ValidatableComponent implements OnChanges } private isSelectable = (value: string): boolean => { - const option: IDropDownOption = this.options.find(o => o.value === value); + // Support ES5 + // const option: IDropDownOption = this.options.find(o => o.value === value); + const option: IDropDownOption = this.options.filter(o => o.value === value)[0]; if (!option) { return false; } if (!option.type) { return true; } - return !this.unselectableOptions.find(optionType => optionType === option.type); + // Support ES5 + // return !this.unselectableOptions.find(optionType => optionType === option.type); + return !this.unselectableOptions.filter(optionType => optionType === option.type)[0]; } private setSelected = (value: string): void => { - this.selectedOption = this.options.find(o => o.value === value); + // Support ES5 + // this.selectedOption = this.options.find(o => o.value === value); + this.selectedOption = this.options.filter(o => o.value === value)[0]; if (this.type === DropDownTypes.Auto) { this.filterValue = value; } this.show = false; this.changeEmitter.next(this.selectedOption); diff --git a/src/angular/form-elements/form-elements.module.ts b/src/angular/form-elements/form-elements.module.ts index 744f8b8..d290eda 100644 --- a/src/angular/form-elements/form-elements.module.ts +++ b/src/angular/form-elements/form-elements.module.ts @@ -1,6 +1,6 @@ import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; -import { InputComponent } from "./input/input.component"; +import { InputComponent } from "./text-elements/input/input.component"; import { DropDownComponent } from "./dropdown/dropdown.component"; import { CommonModule } from "@angular/common"; import { CheckboxComponent } from "./checkbox/checkbox.component"; @@ -9,6 +9,7 @@ import { AnimationDirectivesModule } from '../animations/animation-directives.mo import { DropDownTriggerDirective } from "./dropdown/dropdown-trigger.directive"; import {SvgIconModule} from "../svg-icon/svg-icon.module"; import { ValidationModule } from './validation/validation.module'; +import {TextareaComponent} from "./text-elements/textarea/textarea.component"; @NgModule({ imports: [ @@ -24,6 +25,7 @@ import { ValidationModule } from './validation/validation.module'; CheckboxComponent, RadioGroupComponent, DropDownTriggerDirective, + TextareaComponent ], exports: [ DropDownComponent, @@ -31,7 +33,8 @@ import { ValidationModule } from './validation/validation.module'; InputComponent, CheckboxComponent, RadioGroupComponent, - ValidationModule + ValidationModule, + TextareaComponent ] }) export class FormElementsModule { diff --git a/src/angular/form-elements/radios/radio-buttons-group.component.html.ts b/src/angular/form-elements/radios/radio-buttons-group.component.html.ts index 28a27af..a0026f2 100644 --- a/src/angular/form-elements/radios/radio-buttons-group.component.html.ts +++ b/src/angular/form-elements/radios/radio-buttons-group.component.html.ts @@ -1,7 +1,7 @@ -export default ` +export const template = ` <label class='sdc-radio-group__legend'>{{legend}}</label> <div class='sdc-radio-group__radios {{direction}}'> - <template *ngFor="let item of options.items"> + <div *ngFor="let item of options.items"> <div class="sdc-radio"> <label class="sdc-radio__animation-wrapper" SdcRippleClickAnimation [rippleClickDisabled]="disabled"> <input class="sdc-radio__input" @@ -15,6 +15,6 @@ export default ` <span class="sdc-radio__label">{{ item.label }}</span> </label> </div> - </template> + </div> </div> `; diff --git a/src/angular/form-elements/radios/radio-buttons-group.component.ts b/src/angular/form-elements/radios/radio-buttons-group.component.ts index 800d8b0..9fa6b7d 100644 --- a/src/angular/form-elements/radios/radio-buttons-group.component.ts +++ b/src/angular/form-elements/radios/radio-buttons-group.component.ts @@ -1,6 +1,6 @@ import { Component, Input, Output, ViewEncapsulation, EventEmitter, HostBinding } from "@angular/core"; import { Direction, IOptionGroup, IRadioButtonModel } from "./radio-button.model"; -import template from './radio-buttons-group.component.html'; +import { template } from './radio-buttons-group.component.html'; @Component({ selector: 'sdc-radio-group', @@ -43,9 +43,11 @@ export class RadioGroupComponent { } private isOptionExists(value) { - const exist = this.options.items.find((item: IRadioButtonModel) => { + // Support ES5 + // const exist = this.options.items.find((item: IRadioButtonModel) => { + const exist = this.options.items.filter((item: IRadioButtonModel) => { return item.value === value; - }); + })[0]; return exist !== undefined; } diff --git a/src/angular/form-elements/input/input.component.ts b/src/angular/form-elements/text-elements/base-text-element.component.ts index af0e9f4..a87238f 100644 --- a/src/angular/form-elements/input/input.component.ts +++ b/src/angular/form-elements/text-elements/base-text-element.component.ts @@ -1,15 +1,9 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormControl } from "@angular/forms"; -import { ValidationComponent } from '../validation/validation.component'; -import { ValidatableComponent } from './../validation/validatable.component'; +import { ValidatableComponent } from "../validation/validatable.component"; import 'rxjs/add/operator/debounceTime'; -import template from "./input.component.html"; -@Component({ - selector: 'sdc-input', - template: template, -}) -export class InputComponent extends ValidatableComponent implements OnInit { +export class BaseTextElementComponent extends ValidatableComponent implements OnInit { @Output('valueChange') public baseEmitter: EventEmitter<any> = new EventEmitter<any>(); @Input() public label: string; @@ -17,7 +11,6 @@ export class InputComponent extends ValidatableComponent implements OnInit { @Input() public name: string; @Input() public classNames: string; @Input() public disabled: boolean; - @Input() public type: string; @Input() public placeHolder: string; @Input() public required: boolean; @Input() public minLength: number; @@ -25,19 +18,18 @@ export class InputComponent extends ValidatableComponent implements OnInit { @Input() public debounceTime: number; @Input() public testId: string; - protected control: FormControl; + public control: FormControl; constructor() { super(); this.control = new FormControl('', []); this.debounceTime = 0; this.placeHolder = ''; - this.type = 'text'; } ngOnInit() { this.control.valueChanges. - debounceTime(this.debounceTime) + debounceTime(this.debounceTime) .subscribe((newValue: any) => { this.baseEmitter.emit(this.value); }); diff --git a/src/angular/form-elements/input/input.component.html.ts b/src/angular/form-elements/text-elements/input/input.component.html.ts index f8a4609..bb5d788 100644 --- a/src/angular/form-elements/input/input.component.html.ts +++ b/src/angular/form-elements/text-elements/input/input.component.html.ts @@ -1,9 +1,9 @@ -export default ` +export const template = ` <div class="sdc-input "> <label class="sdc-input__label" *ngIf="label" [ngClass]="{'required':required}">{{label}}</label> <input class="sdc-input__input {{classNames}}" - [ngClass]="{'error': !valid, 'disabled':disabled}" + [ngClass]="{'error': (!valid && dirty), 'disabled':disabled}" [attr.name]="name ? name : null" [placeholder]="placeHolder" [(ngModel)]="value" diff --git a/src/angular/form-elements/text-elements/input/input.component.ts b/src/angular/form-elements/text-elements/input/input.component.ts new file mode 100644 index 0000000..48b177b --- /dev/null +++ b/src/angular/form-elements/text-elements/input/input.component.ts @@ -0,0 +1,18 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { template } from "./input.component.html"; +import { BaseTextElementComponent } from "../base-text-element.component"; +import 'rxjs/add/operator/debounceTime'; + +@Component({ + selector: 'sdc-input', + template: template, +}) +export class InputComponent extends BaseTextElementComponent { + @Input() public type: string; + + constructor() { + super(); + this.type = 'text'; + } + +} diff --git a/src/angular/form-elements/text-elements/textarea/textarea.component.html.ts b/src/angular/form-elements/text-elements/textarea/textarea.component.html.ts new file mode 100644 index 0000000..7e976b2 --- /dev/null +++ b/src/angular/form-elements/text-elements/textarea/textarea.component.html.ts @@ -0,0 +1,18 @@ +export const template = ` +<div class="sdc-textarea"> + <label class="sdc-textarea__label" *ngIf="label" [ngClass]="{'required':required}">{{label}}</label> + <textarea + class="sdc-textarea__textarea {{classNames}}" + [ngClass]="{'error': (!valid && dirty), 'disabled':disabled}" + [attr.name]="name ? name : null" + [placeholder]="placeHolder" + [(ngModel)]="value" + [maxlength]="maxLength" + [minlength]="minLength" + [formControl]="control" + [attr.disabled]="disabled ? 'disabled' : null" + (input)="onKeyPress($event.target.value)" + [attr.data-tests-id]="testId"> + </textarea> +</div> +`; diff --git a/src/angular/form-elements/text-elements/textarea/textarea.component.ts b/src/angular/form-elements/text-elements/textarea/textarea.component.ts new file mode 100644 index 0000000..e8f0700 --- /dev/null +++ b/src/angular/form-elements/text-elements/textarea/textarea.component.ts @@ -0,0 +1,14 @@ +import { Component } from "@angular/core"; +import { template } from './textarea.component.html'; +import { BaseTextElementComponent } from "../base-text-element.component"; + +@Component({ + selector: 'sdc-textarea', + template: template, +}) + +export class TextareaComponent extends BaseTextElementComponent { + constructor() { + super(); + } +} diff --git a/src/angular/form-elements/validation/validatable.component.ts b/src/angular/form-elements/validation/validatable.component.ts index 4817dea..3201e0b 100644 --- a/src/angular/form-elements/validation/validatable.component.ts +++ b/src/angular/form-elements/validation/validatable.component.ts @@ -1,24 +1,24 @@ -import { Input, Component } from "@angular/core"; -import { ValidationComponent } from './validation.component'; import { Subject } from 'rxjs/Subject'; import { IValidatableComponent } from './validatable.interface'; export abstract class ValidatableComponent implements IValidatableComponent { // Each ValidatableComponent should handle the style in case of error, according to this boolean - public valid = true; - + public valid: boolean; + public dirty: boolean; // Each ValidatableComponent will notify when the value is changed. public notifier: Subject<string>; constructor() { this.notifier = new Subject(); + this.dirty = false; } public abstract getValue(): any; // Each ValidatableComponent should call the valueChanged on value changed function. protected valueChanged = (value: any): void => { + this.dirty = true; this.notifier.next(value); } diff --git a/src/angular/form-elements/validation/validation-group.component.html.ts b/src/angular/form-elements/validation/validation-group.component.html.ts index dff591e..4e5e362 100644 --- a/src/angular/form-elements/validation/validation-group.component.html.ts +++ b/src/angular/form-elements/validation/validation-group.component.html.ts @@ -1,3 +1,3 @@ -export default ` +export const template = ` <ng-content></ng-content> `; diff --git a/src/angular/form-elements/validation/validation-group.component.ts b/src/angular/form-elements/validation/validation-group.component.ts index 59ecf4c..4231bbf 100644 --- a/src/angular/form-elements/validation/validation-group.component.ts +++ b/src/angular/form-elements/validation/validation-group.component.ts @@ -1,15 +1,7 @@ import { Input, Component, ContentChildren, EventEmitter, Output, QueryList, SimpleChanges, HostBinding, AfterContentInit } from "@angular/core"; -import { AbstractControl, FormControl } from "@angular/forms"; -import { Subscribable } from "rxjs/Observable"; -import { AnonymousSubscription } from "rxjs/Subscription"; -import { IValidator } from './validators/validator.interface'; import { ValidatorComponent } from './validators/base.validator.component'; -import { RegexValidatorComponent } from './validators/regex.validator.component'; -import { RequiredValidatorComponent } from './validators/required.validator.component'; -import { ValidatableComponent } from './validatable.component'; import { ValidationComponent } from './validation.component'; -import { CustomValidatorComponent } from './validators/custom.validator.component'; -import template from "./validation.component.html"; +import { template } from "./validation-group.component.html"; @Component({ selector: 'sdc-validation-group', @@ -37,7 +29,7 @@ export class ValidationGroupComponent implements AfterContentInit { let validationResult = true; // Iterate over all validationComponent inside the group and return boolean result true in case all validations passed. this.validationsComponents.forEach((validationComponent) => { - if (validationComponent.validate()) { + if (!validationComponent.validate()) { validationResult = false; } }); diff --git a/src/angular/form-elements/validation/validation.component.html.ts b/src/angular/form-elements/validation/validation.component.html.ts index 0f11a23..438cec1 100644 --- a/src/angular/form-elements/validation/validation.component.html.ts +++ b/src/angular/form-elements/validation/validation.component.html.ts @@ -1,3 +1,3 @@ -export default ` -<ng-content *ngIf="!disabled"></ng-content> +export const template = ` +<ng-content *ngIf="!disabled && (validateElement && validateElement.dirty)"></ng-content> `; diff --git a/src/angular/form-elements/validation/validation.component.ts b/src/angular/form-elements/validation/validation.component.ts index 4abdd12..289aeda 100644 --- a/src/angular/form-elements/validation/validation.component.ts +++ b/src/angular/form-elements/validation/validation.component.ts @@ -1,14 +1,10 @@ import { Input, Component, ContentChildren, EventEmitter, Output, QueryList, SimpleChanges, HostBinding, AfterContentInit } from "@angular/core"; -import { AbstractControl, FormControl } from "@angular/forms"; -import { Subscribable } from "rxjs/Observable"; -import { AnonymousSubscription } from "rxjs/Subscription"; -import { IValidator } from './validators/validator.interface'; import { ValidatorComponent } from './validators/base.validator.component'; import { RegexValidatorComponent } from './validators/regex.validator.component'; import { RequiredValidatorComponent } from './validators/required.validator.component'; import { ValidatableComponent } from './validatable.component'; import { CustomValidatorComponent } from './validators/custom.validator.component'; -import template from "./validation.component.html"; +import { template } from "./validation.component.html"; @Component({ selector: 'sdc-validation', @@ -47,6 +43,9 @@ export class ValidationComponent implements AfterContentInit { }, (error) => console.log('Validation subscribe error') ); + // init validateElement.valid. + const value = this.validateElement.getValue(); + this.validateElement.notifier.next(value); } public validate = (): boolean => { diff --git a/src/angular/form-elements/validation/validation.module.ts b/src/angular/form-elements/validation/validation.module.ts index 4213f76..a6aa41e 100644 --- a/src/angular/form-elements/validation/validation.module.ts +++ b/src/angular/form-elements/validation/validation.module.ts @@ -3,7 +3,6 @@ import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { CommonModule } from "@angular/common"; import { SvgIconModule } from './../../svg-icon/svg-icon.module'; import { ValidationComponent } from './validation.component'; -import { ValidatorComponent } from './validators/base.validator.component'; import { RequiredValidatorComponent } from './validators/required.validator.component'; import { RegexValidatorComponent } from './validators/regex.validator.component'; import { CustomValidatorComponent } from './validators/custom.validator.component'; diff --git a/src/angular/form-elements/validation/validators/base.validator.component.html.ts b/src/angular/form-elements/validation/validators/base.validator.component.html.ts index aba8eed..d96ee3b 100644 --- a/src/angular/form-elements/validation/validators/base.validator.component.html.ts +++ b/src/angular/form-elements/validation/validators/base.validator.component.html.ts @@ -1,6 +1,6 @@ -export default ` +export const template = ` <svg-icon-label - *ngIf="!isValid" + *ngIf="!isValid && !disabled" name="alert-triangle" mode="error" size="small" diff --git a/src/angular/form-elements/validation/validators/base.validator.component.ts b/src/angular/form-elements/validation/validators/base.validator.component.ts index 3d751af..8fd0361 100644 --- a/src/angular/form-elements/validation/validators/base.validator.component.ts +++ b/src/angular/form-elements/validation/validators/base.validator.component.ts @@ -1,18 +1,12 @@ import { Input, Component, ContentChildren, EventEmitter, Output, QueryList, SimpleChanges, HostBinding } from "@angular/core"; -import { IValidator } from './validator.interface'; -import template from "./base.validator.component.html"; -@Component({ - selector: 'sdc-validator', - template: template -}) export abstract class ValidatorComponent { @Input() public message: any; @Input() public disabled: boolean; @HostBinding('class') classes; - protected isValid: boolean; + public isValid: boolean; constructor() { this.disabled = false; diff --git a/src/angular/form-elements/validation/validators/custom.validator.component.ts b/src/angular/form-elements/validation/validators/custom.validator.component.ts index eb09636..0ec0e68 100644 --- a/src/angular/form-elements/validation/validators/custom.validator.component.ts +++ b/src/angular/form-elements/validation/validators/custom.validator.component.ts @@ -1,7 +1,7 @@ import { Input, Component } from "@angular/core"; import { ValidatorComponent } from "./base.validator.component"; import { IValidator } from './validator.interface'; -import template from "./base.validator.component.html"; +import { template } from "./base.validator.component.html"; @Component({ selector: 'sdc-custom-validator', diff --git a/src/angular/form-elements/validation/validators/regex.validator.component.ts b/src/angular/form-elements/validation/validators/regex.validator.component.ts index 5929016..5a213a9 100644 --- a/src/angular/form-elements/validation/validators/regex.validator.component.ts +++ b/src/angular/form-elements/validation/validators/regex.validator.component.ts @@ -1,7 +1,7 @@ import { Input, Component } from "@angular/core"; import { ValidatorComponent } from "./base.validator.component"; import { IValidator } from './validator.interface'; -import template from "./base.validator.component.html"; +import { template } from "./base.validator.component.html"; @Component({ selector: 'sdc-regex-validator', diff --git a/src/angular/form-elements/validation/validators/required.validator.component.ts b/src/angular/form-elements/validation/validators/required.validator.component.ts index 7eee932..fc550ca 100644 --- a/src/angular/form-elements/validation/validators/required.validator.component.ts +++ b/src/angular/form-elements/validation/validators/required.validator.component.ts @@ -1,7 +1,7 @@ import { Input, Component } from "@angular/core"; import { ValidatorComponent } from "./base.validator.component"; import { IValidator } from './validator.interface'; -import template from "./base.validator.component.html"; +import { template } from "./base.validator.component.html"; @Component({ selector: 'sdc-required-validator', diff --git a/src/angular/index.html b/src/angular/index.html new file mode 100644 index 0000000..4d9441d --- /dev/null +++ b/src/angular/index.html @@ -0,0 +1,14 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>Ng5test</title> + <base href="/"> + + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="icon" type="image/x-icon" href="favicon.ico"> +</head> +<body> + <storybook-app-root></storybook-app-root> +</body> +</html> diff --git a/src/angular/index.ts b/src/angular/index.ts index e8a54bd..8002604 100644 --- a/src/angular/index.ts +++ b/src/angular/index.ts @@ -15,7 +15,9 @@ import { SearchBarModule } from "./searchbar/search-bar.module"; import { TooltipModule } from "./tooltip/tooltip.module"; import { TagCloudModule } from './tag-cloud/tag-cloud.module'; import { TabsModule } from "./tabs/tabs.module"; +import { LoaderModule } from "./loader/loader.module"; import { AccordionModule } from "./accordion/accordion.module"; +import { MultilineEllipsisModule } from "./multiline-ellipsis/multiline-ellipsis.module"; @NgModule({ imports: [ @@ -35,7 +37,9 @@ import { AccordionModule } from "./accordion/accordion.module"; SvgIconModule, TagCloudModule, TabsModule, - AccordionModule + LoaderModule, + AccordionModule, + MultilineEllipsisModule ], exports: [ AnimationDirectivesModule, @@ -54,15 +58,32 @@ import { AccordionModule } from "./accordion/accordion.module"; SvgIconModule, TagCloudModule, TabsModule, - AccordionModule + LoaderModule, + AccordionModule, + MultilineEllipsisModule ] }) -export class SdcUiComponentsModule { -} +export class SdcUiComponentsModule {} + +export { SdcUiComponentsNg1Module } from './ng1.module'; import * as SdcUiComponents from './components'; +import * as SdcUiServices from './services'; import * as SdcUiCommon from './common/index'; -export { SdcUiComponentsNg1Module } from './ng1.module'; export { SdcUiComponents }; +export { SdcUiServices }; export { SdcUiCommon }; + + + + +// let components = SdcUiComponents; +// let services = SdcUiServices; +// let common = SdcUiCommon + +// export const SdcUi = { +// components, +// services, +// common +// }; diff --git a/src/angular/loader/loader.component.html.ts b/src/angular/loader/loader.component.html.ts new file mode 100644 index 0000000..074854a --- /dev/null +++ b/src/angular/loader/loader.component.html.ts @@ -0,0 +1,13 @@ +export const template = ` +<div class = "sdc-loader-wrapper" *ngIf="!global"> + <div class="sdc-loader-background" *ngIf="active"> + <div class="sdc-loader {{ size }}" *ngIf="active"></div> + </div> + <ng-content></ng-content> +</div> +<div *ngIf="global&&active"> + <div class="sdc-loader-global-wrapper sdc-loader-background" > + <div class="sdc-loader {{ size }}"></div> + </div> +</div> +`; diff --git a/src/angular/loader/loader.component.ts b/src/angular/loader/loader.component.ts new file mode 100644 index 0000000..353a98c --- /dev/null +++ b/src/angular/loader/loader.component.ts @@ -0,0 +1,53 @@ +import { Component, Input, ViewContainerRef, Inject, OnInit, OnDestroy, Output, EventEmitter } from "@angular/core"; +import { template } from "./loader.component.html"; +import { LoaderService } from "./loader.service"; + +export enum LoaderSize { + large = 'large', + medium = 'medium', + small = 'small', +} + +@Component({ + selector: "sdc-loader", + template: template +}) + +export class LoaderComponent implements OnInit, OnDestroy { + @Input() active: number; + @Input() size?: LoaderSize; // small || medium || large + @Input() global?: boolean; // If is relative is set to true, loader will appear over parent element. Otherwise, will be fixed over the entire page. + @Input() name?: string; + @Output() activeChange: EventEmitter<number> = new EventEmitter<number>(); + + constructor(private loaderService: LoaderService) { + this.active = 0; + this.size = LoaderSize.large; + this.global = false; + } + + public ngOnInit(): void { + if (this.name !== undefined) { + this.loaderService.register(this.name, this); + } + } + + public ngOnDestroy(): void { + if (this.name !== undefined) { + this.loaderService.unregister(this.name); + } + } + + public activate() { + this.active++; + this.activeChange.emit(this.active); + } + + public deactivate() { + if (this.active > 0) { + this.active--; + this.activeChange.emit(this.active); + } + } + +} diff --git a/src/angular/loader/loader.module.ts b/src/angular/loader/loader.module.ts new file mode 100644 index 0000000..8914173 --- /dev/null +++ b/src/angular/loader/loader.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from "@angular/core"; +import { LoaderComponent } from "./loader.component"; +import { CommonModule } from "@angular/common"; +import { LoaderService } from "./loader.service"; + +@NgModule({ + declarations: [ + LoaderComponent + ], + imports: [ + CommonModule, + ], + exports: [ + LoaderComponent + ], + providers: [ + LoaderService + ] +}) + +export class LoaderModule {} diff --git a/src/angular/loader/loader.service.ts b/src/angular/loader/loader.service.ts new file mode 100644 index 0000000..288f9bd --- /dev/null +++ b/src/angular/loader/loader.service.ts @@ -0,0 +1,37 @@ +import { Injectable, Type, ComponentRef } from '@angular/core'; +import { LoaderComponent } from './loader.component'; + +@Injectable() +export class LoaderService { + + constructor() {} + + private mainLoaderName = 'general'; + + public registeredLoaders = {}; + + public register(name: string, loader: LoaderComponent) { + if (!this.registeredLoaders[name]) { + this.registeredLoaders[name] = loader; + } + } + + public unregister(name: string) { + if (this.registeredLoaders[name]) { + delete this.registeredLoaders[name]; + } + } + + public activate(name: string = this.mainLoaderName) { + if (this.registeredLoaders[name]) { + this.registeredLoaders[name].activate(); + } + } + + public deactivate(name: string = this.mainLoaderName) { + if (this.registeredLoaders[name]) { + this.registeredLoaders[name].deactivate(); + } + } + +} diff --git a/src/angular/modals/modal-button.component.ts b/src/angular/modals/modal-button.component.ts index 4fa5b7c..07f81dd 100644 --- a/src/angular/modals/modal-button.component.ts +++ b/src/angular/modals/modal-button.component.ts @@ -1,7 +1,6 @@ -import { Component, Input, HostListener } from "@angular/core"; +import { Component, Input, HostListener, EventEmitter, Output } from "@angular/core"; import { ButtonComponent } from "../buttons/button.component"; -import { ModalService } from "./modal.service"; -import template from "./../buttons/button.component.html"; +import { template } from "./../buttons/button.component.html"; @Component({ selector: "sdc-modal-button", @@ -12,16 +11,17 @@ export class ModalButtonComponent extends ButtonComponent { @Input() public id?: string; @Input() public callback: Function; @Input() public closeModal: boolean; + @Output() closeModalEvent: EventEmitter<any> = new EventEmitter<any>(); @HostListener('click') invokeCallback = (): void => { if (this.callback) { this.callback(); } if (this.closeModal) { - this.modalService.closeModal(); + this.closeModalEvent.emit(); } } - constructor(private modalService: ModalService) { + constructor() { super(); this.closeModal = false; } diff --git a/src/angular/modals/modal-close-button.component.ts b/src/angular/modals/modal-close-button.component.ts index e761019..357ff72 100644 --- a/src/angular/modals/modal-close-button.component.ts +++ b/src/angular/modals/modal-close-button.component.ts @@ -1,7 +1,8 @@ -import { Component, Input } from "@angular/core"; -import { ButtonComponent } from "../buttons/button.component"; +import { Component, ComponentRef, Input } from "@angular/core"; import { ModalService } from "./modal.service"; import { RippleAnimationAction } from "../animations/ripple-click.animation.directive"; +import { ModalComponent } from "./modal.component"; +import { ButtonComponent } from "../buttons/button.component"; @Component({ selector: "sdc-modal-close-button", @@ -17,18 +18,20 @@ import { RippleAnimationAction } from "../animations/ripple-click.animation.dire </div> ` }) -export class ModalCloseButtonComponent { +export class ModalCloseButtonComponent extends ButtonComponent { @Input() testId: string; @Input() disabled: boolean; + @Input() modalInstanceRef: ComponentRef<ModalComponent>; public rippleAnimationAction: RippleAnimationAction = RippleAnimationAction.MOUSE_ENTER; constructor(private modalService: ModalService) { + super(); } public closeModal = (): void => { - this.modalService.closeModal(); + this.modalInstanceRef.instance.closeModal(); } } diff --git a/src/angular/modals/modal.component.html.ts b/src/angular/modals/modal.component.html.ts index 90119ac..058c02e 100644 --- a/src/angular/modals/modal.component.html.ts +++ b/src/angular/modals/modal.component.html.ts @@ -1,23 +1,20 @@ -export default ` +export const template = ` +<div class="modal-background" [@toggleBackground]="modalVisible" ></div> <div class="sdc-modal {{size}}"> <div class="sdc-modal__wrapper sdc-modal-type-{{type}}" [@toggleModal]="modalVisible" (@toggleModal.done)="modalToggled($event)"> <div class="sdc-modal__header sdc-{{type}}__header"> - <div class="sdc-modal__icon" *ngIf="type != 'custom'"> - <div *ngIf="type == 'alert'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="alert-a" d="M20.5815,18.7997 C20.3815,18.9997 20.0815,19.0997 19.8815,19.0997 L2.8815,19.0997 C2.6815,19.0997 2.5815,19.0997 2.3815,18.9997 C1.8815,18.6997 1.7815,18.0997 1.9815,17.5997 L10.4815,3.4997 C10.5815,3.4007 10.6815,3.1997 10.7815,3.1997 C11.2815,2.9007 11.8815,3.0997 12.1815,3.4997 L20.6825,17.5997 C20.7815,17.6997 20.7815,17.9007 20.7815,18.0997 C20.8815,18.4007 20.6825,18.5997 20.5815,18.7997 M22.3815,16.5997 L13.9815,2.4007 C13.5815,1.6997 12.8815,1.1997 12.0815,0.9997 C11.2815,0.7997 10.4815,0.9007 9.7815,1.2997 C9.3815,1.4997 8.9815,1.9007 8.7815,2.2997 L0.3815,16.5997 C-0.4185,17.9997 0.0815,19.9007 1.4815,20.6997 C1.8815,20.9997 2.3815,21.0997 2.8815,21.0997 L19.8815,21.0997 C20.6825,21.0997 21.4815,20.7997 21.9815,20.1997 C22.5815,19.5997 22.8815,18.9007 22.8815,18.0997 C22.7815,17.5997 22.6825,16.9997 22.3815,16.5997 M11,7 C10.4,7 10,7.4 10,8 L10,12 C10,12.601 10.4,13 11,13 C11.6,13 12,12.601 12,12 L12,8 C12,7.4 11.6,7 11,7 M10.3,15.3 C10.1,15.499 10,15.699 10,15.999 C10,16.3 10.1,16.499 10.3,16.699 C10.5,16.9 10.7,16.999 11,16.999 C11.3,16.999 11.5,16.9 11.7,16.699 C11.9,16.499 12,16.199 12,15.999 C12,15.8 11.9,15.499 11.7,15.3 C11.3,14.9 10.7,14.9 10.3,15.3"/></defs> - <g fill="none" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#alert-a"/></g></svg></div> - <div *ngIf="type == 'info'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="info-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11,2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.101 4.9,22 11,22 C17.1,22 22,17.101 22,11 C22,4.9 17.1,0 11,0 M11,10 C10.4,10 10,10.4 10,11 L10,15 C10,15.601 10.4,16 11,16 C11.6,16 12,15.601 12,15 L12,11 C12,10.4 11.6,10 11,10 M10.2998,6.2998 C10.0998,6.4998 9.9998,6.6998 9.9998,6.9998 C9.9998,7.2998 10.0998,7.4998 10.2998,7.6998 C10.4998,7.9008 10.6998,7.9998 10.9998,7.9998 C11.2998,7.9998 11.4998,7.9008 11.6998,7.6998 C11.9008,7.4998 11.9998,7.2998 11.9998,6.9998 C11.9998,6.6998 11.9008,6.4998 11.6998,6.2998 C11.2998,5.9008 10.6998,5.9008 10.2998,6.2998"/></defs> - <g fill="none" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#info-a"/></g></svg></div> - <div *ngIf="type == 'error'"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="x-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11,2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.1 4.9,22 11,22 C17.1,22 22,17.1 22,11 C22,4.9 17.1,0 11,0 M14.2591,7.29935 C13.8591,6.90035 13.2591,6.90035 12.8591,7.29935 L10.5591,9.59935 L8.2591,7.29935 C7.8591,6.90035 7.2591,6.90035 6.8591,7.29935 C6.4591,7.69935 6.4591,8.29935 6.8591,8.69935 L9.1581,10.99935 L6.8591,13.29935 C6.4591,13.69935 6.4591,14.29935 6.8591,14.69935 C7.0591,14.90035 7.2591,14.99935 7.5591,14.99935 C7.8591,14.99935 8.0591,14.90035 8.2591,14.69935 L10.5591,12.40035 L12.8591,14.69935 C13.0591,14.90035 13.3591,14.99935 13.5591,14.99935 C13.7591,14.99935 14.0591,14.90035 14.2591,14.69935 C14.6581,14.29935 14.6581,13.69935 14.2591,13.29935 L11.9591,10.99935 L14.2591,8.69935 C14.6581,8.29935 14.6581,7.69935 14.2591,7.29935"/></defs> - <g fill="none" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#x-a"/></g></svg></div> - </div> + <div class="sdc-modal__icon" *ngIf="type!='custom'" [innerHtml]="svgIconContentSafeHtml"></div> <div *ngIf="title" class="title" >{{ title }}</div> - <sdc-modal-close-button #modalCloseButton [testId]="getCalculatedTestId('close')"></sdc-modal-close-button> + <sdc-modal-close-button #modalCloseButton [testId]="getCalculatedTestId('close')" [modalInstanceRef]="instanceRef"></sdc-modal-close-button> </div> - <div class="sdc-modal__content" > - <div *ngIf="message">{{message}}</div> + + <div class="sdc-modal__content"> + <div *ngIf="message" [innerHtml]="message"></div> <div #dynamicContentContainer></div> + <div class="disabled-modal" *ngIf="isDisabled"></div> </div> + <div class="sdc-modal__footer"> <sdc-modal-button *ngFor="let button of buttons" [text]="button.text" @@ -29,10 +26,11 @@ export default ` [show_spinner]="button.show_spinner" [callback]="button.callback" [testId]="getCalculatedTestId('button-' + button.text)" + (closeModalEvent)="closeModal()" > </sdc-modal-button> </div> + </div> </div> -<div class="modal-background" [@toggleBackground]="modalVisible" ></div> `; diff --git a/src/angular/modals/modal.component.spec.ts b/src/angular/modals/modal.component.spec.ts index 372d59d..d1f6b78 100644 --- a/src/angular/modals/modal.component.spec.ts +++ b/src/angular/modals/modal.component.spec.ts @@ -4,102 +4,91 @@ import { NO_ERRORS_SCHEMA } from '@angular/core/src/metadata/ng_module'; import { ModalService } from './modal.service'; import { CreateDynamicComponentService } from "../utils/create-dynamic-component.service"; import { IModalConfig, ModalType, ModalSize } from "../../../src/angular/modals/models/modal-config"; -import { ModalInnerContent } from "../../../stories/ng2-component-lab/components/modal-inner-content-example.component"; - describe("Modal unit-tests", () => { let testService: ModalService; const testInputModal = { - size: 'xl', //'xl|l|md|sm|xsm' + size: 'xl', // 'xl|l|md|sm|xsm' title: 'Test_Title', message: 'Test_Message', modalVisible: true }; beforeEach(async(() => { - TestBed.configureTestingModule({ - providers:[ - ModalService, - { provide : CreateDynamicComponentService, useClass: CreateDynamicComponentServiceTest} - ], - declarations: [], - schemas:[NO_ERRORS_SCHEMA] - }) - testService = TestBed.get(ModalService); + // TestBed.configureTestingModule({ + // providers: [ + // ModalService, + // { provide : CreateDynamicComponentService, useClass: CreateDynamicComponentServiceTest} + // ], + // declarations: [], + // schemas: [NO_ERRORS_SCHEMA] + // }); + // testService = TestBed.get(ModalService); })); it('Modal should be open test', () => { - let modalInstance = testService.openModal(testInputModal); + const modalInstance = testService.openModal(testInputModal); expect(modalInstance).toBeTruthy(); - }) + }); - it('Modal alert window test', () => { - let modalInstance = testService.openAlertModal('testAlert', 'testMessage'); + it('Modal warning window test', () => { + const modalInstance = testService.openWarningModal('Worning title', 'testAlert', 'testMessage'); expect(modalInstance).toBeTruthy(); - }) + }); it('Modal info window test', () => { - let modalInstance = testService.openErrorModal('testMessage', 'sampleTestId'); + const modalInstance = testService.openErrorModal('Error title', 'testMessage', 'sampleTestId'); expect(modalInstance).toBeTruthy(); - }) - - - it('Custom Modal should be open', () => { - let modalConfig:IModalConfig = <IModalConfig> { - size: ModalSize.medium, - title: 'Title', - type: ModalType.custom, - buttons: [{text:"Save & Close", closeModal:true}, - {text:"Save", callback:this.customModalOnSave, closeModal:false}, - {text:"Cancel", type: 'secondary', closeModal:true}] - }; - let modalInstance = testService.openCustomModal(modalConfig, ModalInnerContent, {name: "Sample Content"}); - expect(modalInstance).toBeTruthy(); - }) - - it('Shoul close window', () => { - let modalInstance = testService.openModal(testInputModal); - testService.closeModal(); - expect(modalInstance.instance.modalVisible).toBeFalsy(); - }) -}) - + }); + + // it('Custom Modal should be open', () => { + // const modalConfig: IModalConfig = { + // size: ModalSize.medium, + // title: 'Title', + // type: ModalType.custom, + // buttons: [{text: "Save & Close", closeModal: true}, + // {text: "Save", callback: this.customModalOnSave, closeModal: false}, + // {text: "Cancel", type: 'secondary', closeModal: true}] + // } as IModalConfig; + // const modalInstance = testService.openCustomModal(modalConfig, ModalInnerContent, {name: "Sample Content"}); + // expect(modalInstance).toBeTruthy(); + // }); + + // it('Should close window', () => { + // const modalInstance = testService.openModal(testInputModal); + // modalInstance.instance.closeModal(); + // expect(modalInstance.instance.modalVisible).toBeFalsy(); + // }); +}); const testModalInstance = { - instance:{ - closeAnimationComplete:{ - subscribe:() => { + instance: { + closeAnimationComplete: { + subscribe: () => { return true; }, }, - _createDynamicComponentService:{ - insertComponentDynamically:() => { + _createDynamicComponentService: { + insertComponentDynamically: () => { return true; } }, - modalVisible:true - }, - -}; - -@Component({ - selector: 'modal-test', - template: `<div></div>` -}) - - - -export class CreateDynamicComponentServiceTest { - modalVisble: true; - public createComponentDynamically = (modalInstance, customData) => { - return testModalInstance; - } - public insertComponentDynamically = () =>{ - return testModalInstance; + modalVisible: true } +}; -} - - - - +// @Component({ +// selector: 'modal-test', +// template: `<div></div>` +// }) + +// export class CreateDynamicComponentServiceTest { +// modalVisble: true; +// public createComponentDynamically = (modalInstance, customData) => { +// return testModalInstance; +// } +// public insertComponentDynamically = () => { +// return testModalInstance; +// } + +// } diff --git a/src/angular/modals/modal.component.ts b/src/angular/modals/modal.component.ts index 4f4d81f..c6f346c 100644 --- a/src/angular/modals/modal.component.ts +++ b/src/angular/modals/modal.component.ts @@ -1,33 +1,36 @@ -import { Component, Input, Output, ViewContainerRef, ViewChild, ComponentRef, trigger, state, animate, transition, style, EventEmitter, Renderer, ElementRef } from '@angular/core'; +import { Component, Input, ViewContainerRef, ViewChild, ComponentRef, Renderer, OnInit } from '@angular/core'; +import { animate, style, transition, trigger } from '@angular/animations'; import { ModalButtonComponent } from './modal-button.component'; import { LowerCasePipe } from '@angular/common'; import { ModalCloseButtonComponent } from './modal-close-button.component'; -import template from './modal.component.html'; +import { ModalType } from './models/modal-config'; +import { template } from './modal.component.html'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Component({ selector: 'sdc-modal', template: template, animations: [ trigger('toggleBackground', [ - transition('* => 1', [style({opacity: 0}), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]), - transition('1 => *', [animate('.35s cubic-bezier(0.23, 1, 0.32, 1)', style({opacity: 0}))]) + transition('* => 1', [style({ opacity: 0 }), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]), + transition('1 => *', [animate('.35s cubic-bezier(0.23, 1, 0.32, 1)', style({ opacity: 0 }))]) ]), trigger('toggleModal', [ - transition('* => 1', [style({opacity: 0, transform: 'translateY(-80px)'}), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]), - transition('1 => *', [style({opacity: 1, transform: 'translateY(0px)'}), animate('.35s ease-in-out', style({opacity:0, transform: 'translateY(-80px)'}))]) + transition('* => 1', [style({ opacity: 0, transform: 'translateY(-80px)' }), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]), + transition('1 => *', [style({ opacity: 1, transform: 'translateY(0px)' }), animate('.35s ease-in-out', style({ opacity: 0, transform: 'translateY(-80px)' }))]) ]) ] }) -export class ModalComponent { +export class ModalComponent implements OnInit { @Input() size: string; 'xl|l|md|sm|xsm'; @Input() title: string; @Input() message: string; @Input() buttons: ModalButtonComponent[]; - @Input() type: string; 'info|error|alert|custom'; + @Input() type: ModalType; @Input() testId: string; - @Output() closeAnimationComplete: EventEmitter<any> = new EventEmitter<any>(); + @Input() instanceRef: ComponentRef<ModalComponent>; // the component ref is injected to the component in order to destroy the componet from itself @ViewChild('modalCloseButton') set refCloseButton(_modalCloseButton: ModalCloseButtonComponent) { @@ -36,19 +39,68 @@ export class ModalComponent { modalVisible: boolean; // Allows for custom component as body instead of simple message. - // See ModalService.createActionModal for implementation details, and HttpService's catchError() for example. - @ViewChild('dynamicContentContainer', {read: ViewContainerRef}) dynamicContentContainer: ViewContainerRef; - innerModalContent: ComponentRef<ModalComponent>; + @ViewChild('dynamicContentContainer', { read: ViewContainerRef }) dynamicContentContainer: ViewContainerRef; + innerModalContent: ComponentRef<any>; public calculatedTestId: string; public modalCloseButton: ModalCloseButtonComponent; + public svgIconContentSafeHtml: SafeHtml; + public isDisabled: boolean; + + private infoSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"> + <defs><path fill="#000" id="info-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11,2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.101 4.9,22 11,22 C17.1,22 22,17.101 22,11 C22,4.9 17.1,0 11,0 M11,10 C10.4, + 10 10,10.4 10,11 L10,15 C10,15.601 10.4,16 11,16 C11.6,16 12,15.601 12,15 L12,11 C12,10.4 11.6,10 11,10 M10.2998,6.2998 C10.0998,6.4998 9.9998,6.6998 9.9998,6.9998 C9.9998,7.2998 10.0998,7.4998 10.2998,7.6998 C10.4998, + 7.9008 10.6998,7.9998 10.9998,7.9998 C11.2998,7.9998 11.4998,7.9008 11.6998,7.6998 C11.9008,7.4998 11.9998,7.2998 11.9998,6.9998 C11.9998,6.6998 11.9008,6.4998 11.6998,6.2998 C11.2998,5.9008 10.6998,5.9008 10.2998,6.2998"/> + </defs><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#info-a"/></g></svg>`; + private warningSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="alert-a" d="M20.5815,18.7997 C20.3815, + 18.9997 20.0815,19.0997 19.8815,19.0997 L2.8815,19.0997 C2.6815,19.0997 2.5815,19.0997 2.3815,18.9997 C1.8815,18.6997 1.7815,18.0997 1.9815,17.5997 L10.4815,3.4997 C10.5815,3.4007 10.6815,3.1997 10.7815,3.1997 C11.2815, + 2.9007 11.8815,3.0997 12.1815,3.4997 L20.6825,17.5997 C20.7815,17.6997 20.7815,17.9007 20.7815,18.0997 C20.8815,18.4007 20.6825,18.5997 20.5815,18.7997 M22.3815,16.5997 L13.9815,2.4007 C13.5815,1.6997 12.8815,1.1997 12.0815, + 0.9997 C11.2815,0.7997 10.4815,0.9007 9.7815,1.2997 C9.3815,1.4997 8.9815,1.9007 8.7815,2.2997 L0.3815,16.5997 C-0.4185,17.9997 0.0815,19.9007 1.4815,20.6997 C1.8815,20.9997 2.3815,21.0997 2.8815,21.0997 L19.8815, + 21.0997 C20.6825,21.0997 21.4815,20.7997 21.9815,20.1997 C22.5815,19.5997 22.8815,18.9007 22.8815,18.0997 C22.7815,17.5997 22.6825,16.9997 22.3815,16.5997 M11,7 C10.4,7 10,7.4 10,8 L10,12 C10,12.601 10.4,13 11,13 C11.6,13 12, + 12.601 12,12 L12,8 C12,7.4 11.6,7 11,7 M10.3,15.3 C10.1,15.499 10,15.699 10,15.999 C10,16.3 10.1,16.499 10.3,16.699 C10.5,16.9 10.7,16.999 11,16.999 C11.3,16.999 11.5,16.9 11.7,16.699 C11.9,16.499 12,16.199 12,15.999 C12, + 15.8 11.9,15.499 11.7,15.3 C11.3,14.9 10.7,14.9 10.3,15.3"/></defs><g fill="#ffb81c" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#alert-a"/></g></svg>`; + private errorSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="x-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11, + 2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.1 4.9,22 11,22 C17.1,22 22,17.1 22,11 C22,4.9 17.1,0 11,0 M14.2591,7.29935 C13.8591,6.90035 13.2591,6.90035 12.8591,7.29935 L10.5591,9.59935 L8.2591, + 7.29935 C7.8591,6.90035 7.2591,6.90035 6.8591,7.29935 C6.4591,7.69935 6.4591,8.29935 6.8591,8.69935 L9.1581,10.99935 L6.8591,13.29935 C6.4591,13.69935 6.4591,14.29935 6.8591,14.69935 C7.0591,14.90035 7.2591,14.99935 7.5591, + 14.99935 C7.8591,14.99935 8.0591,14.90035 8.2591,14.69935 L10.5591,12.40035 L12.8591,14.69935 C13.0591,14.90035 13.3591,14.99935 13.5591,14.99935 C13.7591,14.99935 14.0591,14.90035 14.2591,14.69935 C14.6581,14.29935 14.6581, + 13.69935 14.2591,13.29935 L11.9591,10.99935 L14.2591,8.69935 C14.6581,8.29935 14.6581,7.69935 14.2591,7.29935"/></defs><g fill="none" fill-rule="evenodd" transform="translate(1 1)"> + <use class="sdc-modal__svg-use" xlink:href="#x-a"/></g></svg>`; + private successSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24" fill="#4ca90c"><path id="success+20-a" d="M20.1825992,10.445793 C20.6735306, + 10.445793 21.0008182,10.7730806 21.0008182,11.264012 L21.0008182,12.0004091 C21.0008182,16.9915451 16.9915451,21 12.0004091,21 C7.00927315,21 3,16.9915451 3,12.0004091 C3,7.00927315 7.00927315,3 12.0004091,3 C13.3095595,3 14.536888, + 3.3272876 15.6823947,3.81821901 C16.0915042,3.98186281 16.255148,4.47279422 16.0915042,4.88190372 C15.9278604,5.29101323 15.436929,5.45465703 15.0278194,5.29101323 C14.0459566,4.88190372 13.0640938,4.63643802 12.0004091, + 4.63643802 C7.90931406,4.63643802 4.63643802,7.90931406 4.63643802,12.0004091 C4.63643802,16.0906859 7.90931406,19.363562 12.0004091,19.363562 C16.0915042,19.363562 19.3643802,16.0906859 19.3643802,12.0004091 L19.3643802, + 11.264012 C19.3643802,10.7730806 19.6916678,10.445793 20.1825992,10.445793 Z M21.5737352,4.06343925 C21.9002046,4.39072685 21.9002046,4.88165826 21.5737352,5.20894586 L12.5733261,14.209355 C12.4096823,14.3729988 12.1642166, + 14.4548207 12.0005728,14.4548207 C11.836929,14.4548207 11.5914632,14.3729988 11.4278194,14.209355 L8.97316242,11.7546979 C8.64587481,11.4274103 8.64587481,10.9364789 8.97316242,10.6091913 C9.30045002,10.2819037 9.79138143, + 10.2819037 10.118669,10.6091913 L12.0005728,12.491095 L20.4282286,4.06343925 C20.7555162,3.73615164 21.2464476,3.73615164 21.5737352,4.06343925 Z"></path></svg>`; + private noSvg = ``; constructor(private renderer: Renderer, - private lowerCasePipe: LowerCasePipe - ) { + private domSanitizer: DomSanitizer, + private lowerCasePipe: LowerCasePipe + ) { this.modalVisible = true; } + ngOnInit() { + + switch (this.type) { + case ModalType.info: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.infoSvg); + break; + case ModalType.warning: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.warningSvg); + break; + case ModalType.error: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.errorSvg); + break; + case ModalType.success: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.successSvg); + break; + default: + this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.noSvg); + } + } + getCalculatedTestId = (buttonText: string): string => { // TODO: Replace this if (this.testId) { @@ -59,7 +111,7 @@ export class ModalComponent { public modalToggled = (toggleEvent: any) => { if (!toggleEvent.toState) { - this.closeAnimationComplete.emit(); + this.instanceRef.destroy(); } } @@ -68,9 +120,11 @@ export class ModalComponent { } public getButtonById = (id: string): ModalButtonComponent => { - return this.buttons.find((button) => { + // Support ES5 + // return this.buttons.find((button) => { + return this.buttons.filter((button) => { return button.id && button.id === id; - }); + })[0]; } public getButtons = (): ModalButtonComponent[] => { @@ -93,4 +147,16 @@ export class ModalComponent { this.renderer.setElementClass(evn.target as HTMLElement, 'sdc-ripple-click__animated', true); // evn.taregt.classList.add('sdc-ripple-click__animated'); } + + public closeModal = (): void => { + this.modalVisible = false; + } + + public disabledModal = (isDisabled: boolean): void => { + this.isDisabled = isDisabled; + this.buttons.forEach((button: ModalButtonComponent) => { + button.disabled = isDisabled; + }); + this.modalCloseButton.disabled = isDisabled; + } } diff --git a/src/angular/modals/modal.service.ts b/src/angular/modals/modal.service.ts index d80ad1f..231b062 100644 --- a/src/angular/modals/modal.service.ts +++ b/src/angular/modals/modal.service.ts @@ -2,99 +2,59 @@ import { Injectable, Type, ComponentRef } from '@angular/core'; import { ModalComponent } from "./modal.component"; import { CreateDynamicComponentService } from "../utils/create-dynamic-component.service"; import { IModalConfig, ModalType, ModalSize, IModalButtonComponent } from "./models/modal-config"; +import { ButtonType } from '../common/enums'; +import { ModalButtonComponent } from './modal-button.component'; @Injectable() export class ModalService { - private currentModal: ComponentRef<any>; - constructor(private createDynamicComponentService: CreateDynamicComponentService) { } - /* Shortcut method to open an alert modal with title, message, and close button that simply closes the modal. */ - public openAlertModal(title: string, message: string, actionButtonText?: string, actionButtonCallback?: Function, testId?: string) { + private getBaseModal = (type: ModalType | ButtonType, title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { const modalConfig = { size: ModalSize.small, title: title, message: message, testId: testId, - buttons: this.createButtons('secondary', actionButtonText, actionButtonCallback), - type: ModalType.alert - } as IModalConfig; - const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig); - this.currentModal = modalInstance; - return modalInstance; - } - - public openActionModal = (title: string, message: string, actionButtonText?: string, actionButtonCallback?: Function, testId?: string): ComponentRef<ModalComponent> => { - const modalConfig = { - size: ModalSize.small, - title: title, - message: message, - testId: testId, - type: ModalType.standard, - buttons: this.createButtons('primary', actionButtonText, actionButtonCallback) - } as IModalConfig; - const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig); - this.currentModal = modalInstance; - return modalInstance; - } - - public openErrorModal = (errorMessage?: string, testId?: string): ComponentRef<ModalComponent> => { - const modalConfig = { - size: ModalSize.small, - title: 'Error', - message: errorMessage, - testId: testId, - buttons: [{text: "OK", type: "alert", closeModal: true}], - type: ModalType.error + buttons: buttons ? buttons : [{ text: 'OK', type: type, closeModal: true }], + type: type } as IModalConfig; const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig); - this.currentModal = modalInstance; - return modalInstance; + return modalInstance.instance; } - public openCustomModal = (modalConfig: IModalConfig, dynamicComponentType: Type<any>, dynamicComponentInput?: any) => { - const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig); - this.createInnnerComponent(dynamicComponentType, dynamicComponentInput); - return modalInstance; + /* Shortcut method to open basic modals with title, message, and OK button that simply closes the modal. */ + public openInfoModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + return this.getBaseModal(ModalType.info, title, message, testId, buttons); } - public createInnnerComponent = (dynamicComponentType: Type<any>, dynamicComponentInput?: any): void => { - this.currentModal.instance.innerModalContent = this.createDynamicComponentService.insertComponentDynamically(dynamicComponentType, dynamicComponentInput, this.currentModal.instance.dynamicContentContainer); + public openWarningModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + return this.getBaseModal(ModalType.warning, title, message, testId, buttons); } - public openModal = (customModalData: IModalConfig): ComponentRef<ModalComponent> => { - const modalInstance: ComponentRef<ModalComponent> = this.createDynamicComponentService.createComponentDynamically(ModalComponent, customModalData); - modalInstance.instance.closeAnimationComplete.subscribe(() => { - this.destroyModal(); - }); - this.currentModal = modalInstance; - return modalInstance; + public openErrorModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + return this.getBaseModal(ModalType.error, title, message, testId, buttons); } - public getCurrentInstance = () => { - return this.currentModal.instance; + public openSuccessModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => { + return this.getBaseModal(ModalType.success, title, message, testId, buttons); } - public closeModal = (): void => { // triggers closeModal animation, which then triggers toggleModal.done and the subscription to destroyModal - this.currentModal.instance.modalVisible = false; + public openCustomModal = (modalConfig: IModalConfig, dynamicComponentType: Type<any>, dynamicComponentInput?: any) => { + const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig); + this.createInnnerComponent(modalInstance, dynamicComponentType, dynamicComponentInput); + return modalInstance.instance; } - private createButtons = (type: string, actionButtonText?: string, actionButtonCallback?: Function): Array<IModalButtonComponent> => { - const buttons: Array<IModalButtonComponent> = []; - if (actionButtonText && actionButtonCallback) { - buttons.push({text: actionButtonText, type: type, callback: actionButtonCallback, closeModal: true}); - buttons.push({text: 'Cancel', type: 'secondary', closeModal: true}); - } else { - buttons.push({text: 'Cancel', type: type, closeModal: true}); - } - - return buttons; + public createInnnerComponent = (modalInstance: ComponentRef<ModalComponent>, dynamicComponentType: Type<any>, dynamicComponentInput?: any): void => { + modalInstance.instance.innerModalContent = this.createDynamicComponentService.insertComponentDynamically(dynamicComponentType, dynamicComponentInput, modalInstance.instance.dynamicContentContainer); } - private destroyModal = (): void => { - this.currentModal.destroy(); + public openModal = (customModalData: IModalConfig): ComponentRef<ModalComponent> => { + let modalInstance: ComponentRef<ModalComponent> = this.createDynamicComponentService.createComponentDynamically(ModalComponent, customModalData); + modalInstance.instance.instanceRef = modalInstance; + return modalInstance; } } diff --git a/src/angular/modals/models/modal-config.ts b/src/angular/modals/models/modal-config.ts index 635942b..8cf955e 100644 --- a/src/angular/modals/models/modal-config.ts +++ b/src/angular/modals/models/modal-config.ts @@ -1,4 +1,4 @@ -import { Placement } from "../../common/enums"; +import { IButtonComponent } from "../../buttons/ibutton.interface"; export interface IModalConfig { size?: string; // xl|l|md|sm|xsm @@ -6,33 +6,22 @@ export interface IModalConfig { message?: string; buttons?: IModalButtonComponent[]; testId?: string; - type?: string; // 'info|error|alert'; + type?: ModalType; } -export interface IButtonComponent { - text: string; - disabled?: boolean; - type?: string; - testId?: string; - preventDoubleClick?: boolean; - icon_name?: string; - icon_position?: string; - show_spinner?: boolean; - spinner_position?: Placement; - size?: string; -} - -export interface IModalButtonComponent extends IButtonComponent{ +export interface IModalButtonComponent extends IButtonComponent { id?: string; - callback?: Function; + callback?: () => void; closeModal?: boolean; } export enum ModalType { - alert = "alert", - error = "error", - standard = "info", - custom = "custom" + info = 'info', + warning = 'warning', + error = 'error', + success = 'success', + action = 'action', + custom = 'custom' } export enum ModalSize { diff --git a/src/angular/multiline-ellipsis/multiline-ellipsis.component.html.ts b/src/angular/multiline-ellipsis/multiline-ellipsis.component.html.ts new file mode 100644 index 0000000..ecaeb42 --- /dev/null +++ b/src/angular/multiline-ellipsis/multiline-ellipsis.component.html.ts @@ -0,0 +1,8 @@ +export const template = ` +<div class="multiline-ellipsis-container" [ngClass]="className" [ngStyle]="stylesContainer" #multilineEllipsisContainer> + <div class="multiline-ellipsis-content" [ngStyle]="stylesContent" #multilineEllipsisContent> + <ng-content></ng-content> + <div class="multiline-ellipsis-dots" [ngStyle]="stylesDots"></div> + </div> +</div> +`; diff --git a/src/angular/multiline-ellipsis/multiline-ellipsis.component.ts b/src/angular/multiline-ellipsis/multiline-ellipsis.component.ts new file mode 100644 index 0000000..bc7f805 --- /dev/null +++ b/src/angular/multiline-ellipsis/multiline-ellipsis.component.ts @@ -0,0 +1,70 @@ +import { Component, OnChanges, AfterViewChecked, ViewChild, ElementRef, Input, Output, SimpleChanges, EventEmitter } from "@angular/core"; +import { template } from './multiline-ellipsis.component.html'; + +declare const window: any; + +@Component({ + selector: 'multiline-ellipsis', + template: template +}) + +export class MultilineEllipsisComponent implements OnChanges, AfterViewChecked { + + @Input() public lines: number; + @Input() public lineHeight: string; + @Input() public className: string; + @Output() public hasEllipsisChanged: EventEmitter<boolean>; + + @ViewChild('multilineEllipsisContainer') public elmContainer: ElementRef; + @ViewChild('multilineEllipsisContent') public elmContent: ElementRef; + + public stylesContainer: { [key: string]: string }; + public stylesContent: { [key: string]: string }; + public stylesDots: { [key: string]: string }; + + private hasEllipsis: boolean; + + public constructor() { + this.hasEllipsisChanged = new EventEmitter<boolean>(); + } + + public ngOnChanges(changes: SimpleChanges) { + this.prepareStyles() + } + + public ngAfterViewChecked() { + const hasEllipsis = (this.elmContainer.nativeElement.offsetHeight < this.elmContent.nativeElement.offsetHeight); + if (hasEllipsis !== this.hasEllipsis) { + this.hasEllipsis = hasEllipsis; + setTimeout(() => { + this.hasEllipsisChanged.emit(this.hasEllipsis); + }); + } + } + + private prepareStyles() { + const lineHeight = this.lineHeight || this.getLineHeight(); + this.stylesContainer = { + 'max-height': `calc(${this.lines} * ${lineHeight})` + }; + this.stylesContent = { + 'max-height': `calc(${this.lines + 1} * ${lineHeight})` + }; + this.stylesDots = { + 'top': `calc(${2 * this.lines} * ${lineHeight} - 100%)` + }; + } + + private getLineHeight() { + let lineHeight: number = parseFloat(window.getComputedStyle(this.elmContainer.nativeElement)['line-height']); + if (!lineHeight) { + const oneLetterElm = window.document.createElement('div'); + oneLetterElm.innerText = '.'; + this.elmContainer.nativeElement.append(oneLetterElm); + lineHeight = oneLetterElm.clientHeight; + this.elmContainer.nativeElement.removeChild(oneLetterElm); + } + return `${lineHeight}px`; + } + +} diff --git a/src/angular/multiline-ellipsis/multiline-ellipsis.module.ts b/src/angular/multiline-ellipsis/multiline-ellipsis.module.ts new file mode 100644 index 0000000..24ed7b3 --- /dev/null +++ b/src/angular/multiline-ellipsis/multiline-ellipsis.module.ts @@ -0,0 +1,11 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {MultilineEllipsisComponent} from './multiline-ellipsis.component'; + +@NgModule({ + declarations: [MultilineEllipsisComponent], + imports: [CommonModule], + exports: [MultilineEllipsisComponent], + entryComponents: [MultilineEllipsisComponent] +}) +export class MultilineEllipsisModule {} diff --git a/src/angular/ng1.module.ts b/src/angular/ng1.module.ts index 6f636f4..4aba999 100644 --- a/src/angular/ng1.module.ts +++ b/src/angular/ng1.module.ts @@ -1,6 +1,6 @@ -import { SdcUiComponentsModule } from './index'; import { downgradeComponent, downgradeInjectable } from "@angular/upgrade/static"; import * as Components from './components'; +import * as Services from './services'; declare const angular: any; let SdcUiComponentsNg1Module = null; @@ -38,7 +38,7 @@ if (typeof angular !== "undefined") { })); // Modals - SdcUiComponentsNg1Module.service('SdcModalService', downgradeInjectable(Components.ModalService)); + SdcUiComponentsNg1Module.service('SdcModalService', downgradeInjectable(Services.ModalService)); SdcUiComponentsNg1Module.directive('sdcModal', downgradeComponent({ component: Components.ModalComponent, inputs: ['size', 'title', 'message', 'buttons', 'type'], @@ -50,7 +50,7 @@ if (typeof angular !== "undefined") { })); // Notifications - SdcUiComponentsNg1Module.service('SdcNotificationService', downgradeInjectable(Components.NotificationsService)); + SdcUiComponentsNg1Module.service('SdcNotificationService', downgradeInjectable(Services.NotificationsService)); SdcUiComponentsNg1Module.directive('sdcNotificationContainer', downgradeComponent({ component: Components.NotificationContainerComponent })); @@ -130,6 +130,13 @@ if (typeof angular !== "undefined") { inputs: ['arrow-direction', 'css-class', 'title', 'open'], outputs: ['accordionChanged'] })); + + // Multiline Ellipsis + SdcUiComponentsNg1Module.directive('multilineEllipsis', downgradeComponent({ + component: Components.MultilineEllipsisComponent, + inputs: ['lines', 'line-height', 'className'], + outputs: ['hasEllipsisChanged'] + })); } -export {SdcUiComponentsNg1Module}; +export { SdcUiComponentsNg1Module }; diff --git a/src/angular/notifications/container/notifcontainer.component.html.ts b/src/angular/notifications/container/notifcontainer.component.html.ts index df08bb4..4073f47 100644 --- a/src/angular/notifications/container/notifcontainer.component.html.ts +++ b/src/angular/notifications/container/notifcontainer.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div id="containerid" class="sdc-notification-container ntns"> <sdc-notification *ngFor="let notif of notifications" [notificationSetting]="notif" (destroyComponent)="onDestroyed(notif)" > </sdc-notification> diff --git a/src/angular/notifications/container/notifcontainer.component.ts b/src/angular/notifications/container/notifcontainer.component.ts index a922dc1..d2f7ad1 100644 --- a/src/angular/notifications/container/notifcontainer.component.ts +++ b/src/angular/notifications/container/notifcontainer.component.ts @@ -1,8 +1,7 @@ import { Component, Input, Output, EventEmitter, OnInit } from "@angular/core"; -import { CommonModule } from "@angular/common"; import { NotificationSettings } from "../utilities/notification.config"; import { NotificationsService } from "../services/notifications.service"; -import template from "./notifcontainer.component.html"; +import { template } from "./notifcontainer.component.html"; @Component({ selector: "sdc-notification-container", @@ -14,14 +13,13 @@ export class NotificationContainerComponent implements OnInit { constructor(private notify: NotificationsService) { } - public ngOnInit(){ - this.notify.subscribe( (notif : NotificationSettings) => { + public ngOnInit() { + this.notify.subscribe((notif: NotificationSettings) => { this.notifications.push(notif); }); } - - private onDestroyed = (event : any):void =>{ + private onDestroyed = (event: any): void => { let index: number = this.notifications.indexOf(event); if (index !== -1) { this.notifications.splice(index, 1); diff --git a/src/angular/notifications/notification-inner-content-example.component.ts b/src/angular/notifications/notification-inner-content-example.component.ts index 552f7b0..fbda881 100644 --- a/src/angular/notifications/notification-inner-content-example.component.ts +++ b/src/angular/notifications/notification-inner-content-example.component.ts @@ -14,8 +14,9 @@ import { Component, Input } from "@angular/core"; </div> ` }) + export class InnerNotifContent { - @Input() notifyTitle:string; - @Input() notifyText:string; + @Input() notifyTitle: string; + @Input() notifyText: string; } diff --git a/src/angular/notifications/notification.module.ts b/src/angular/notifications/notification.module.ts index 5891391..4241b5d 100644 --- a/src/angular/notifications/notification.module.ts +++ b/src/angular/notifications/notification.module.ts @@ -4,18 +4,21 @@ import { NotificationComponent } from "./notification/notification.component"; import { NotificationContainerComponent } from "./container/notifcontainer.component"; import { NotificationsService } from "./services/notifications.service"; import { CreateDynamicComponentService } from "../utils/create-dynamic-component.service"; - +import { InnerNotifContent } from "./notification-inner-content-example.component"; @NgModule({ declarations: [ + InnerNotifContent, NotificationComponent, NotificationContainerComponent, ], exports: [ + InnerNotifContent, NotificationComponent, NotificationContainerComponent, ], entryComponents: [ + InnerNotifContent, NotificationComponent, NotificationContainerComponent, ], diff --git a/src/angular/notifications/notification/notification.component.html.ts b/src/angular/notifications/notification/notification.component.html.ts index 450972e..eff98c8 100644 --- a/src/angular/notifications/notification/notification.component.html.ts +++ b/src/angular/notifications/notification/notification.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="sdc-notification" (click)="fadeOut()"> <div class="sdc-notification__wrapper {{'type-' + notificationSetting.type}}" [class.fade-out__animated]="fade" (animationend)="destroyMe()"> <div *ngIf="!notificationSetting.hasCustomContent" class="sdc-notification__content"> diff --git a/src/angular/notifications/notification/notification.component.ts b/src/angular/notifications/notification/notification.component.ts index 476853c..8b89467 100644 --- a/src/angular/notifications/notification/notification.component.ts +++ b/src/angular/notifications/notification/notification.component.ts @@ -1,7 +1,7 @@ import { Component, Input, Output, EventEmitter, OnInit, ViewContainerRef, ViewChild } from "@angular/core"; import { NotificationSettings } from "../utilities/notification.config"; import { CreateDynamicComponentService } from "../../utils/create-dynamic-component.service"; -import template from "./notification.component.html"; +import { template } from "./notification.component.html"; @Component({ selector: 'sdc-notification', @@ -10,31 +10,31 @@ import template from "./notification.component.html"; export class NotificationComponent implements OnInit { - @Input() notificationSetting:NotificationSettings; + @Input() notificationSetting: NotificationSettings; @Output() destroyComponent = new EventEmitter<any>(); - @ViewChild("dynamicContentContainer", {read: ViewContainerRef}) contentContainer:ViewContainerRef; - private fade: boolean = false; + @ViewChild("dynamicContentContainer", { read: ViewContainerRef }) contentContainer: ViewContainerRef; + public fade: boolean = false; constructor(private createDynamicComponentService: CreateDynamicComponentService) { } public ngOnInit() { - if(this.notificationSetting.hasCustomContent){ + if (this.notificationSetting.hasCustomContent) { this.createDynamicComponentService.insertComponentDynamically(this.notificationSetting.innerComponentType, this.notificationSetting.innerComponentOptions, this.contentContainer); } - if(!this.notificationSetting.sticky){ + if (!this.notificationSetting.sticky) { setTimeout(() => this.fadeOut(), this.notificationSetting.duration); } } - private fadeOut = ():void => { + public fadeOut = (): void => { this.fade = true; } - private destroyMe() { + public destroyMe() { /*Only destroy on fade out, not on entry animation */ - if(this.fade){ + if (this.fade) { this.destroyComponent.emit(this.notificationSetting); } } diff --git a/src/angular/notifications/services/notifications.service.ts b/src/angular/notifications/services/notifications.service.ts index 28a645c..8c77e20 100644 --- a/src/angular/notifications/services/notifications.service.ts +++ b/src/angular/notifications/services/notifications.service.ts @@ -3,39 +3,33 @@ import { NotificationSettings } from '../utilities/notification.config' import { Subject } from 'rxjs/Subject'; import { Subscription } from 'rxjs/Subscription'; - @Injectable() export class NotificationsService { - notifs : NotificationSettings[] = []; + notifs: NotificationSettings[] = []; - notifQueue : Subject<any> = new Subject<any>(); + notifQueue: Subject<any> = new Subject<any>(); constructor() {} - public push(notif : NotificationSettings):void{ + public push(notif: NotificationSettings): void { - if( this.notifQueue.observers.length > 0 ) { + if ( this.notifQueue.observers.length > 0 ) { this.notifQueue.next(notif); } else { this.notifs.push(notif); } } - - - public getNotifications() : NotificationSettings[] { + public getNotifications(): NotificationSettings[] { return this.notifs; } - - public subscribe(observer): Subscription { - let s:Subscription = this.notifQueue.subscribe(observer); + const s: Subscription = this.notifQueue.subscribe(observer); this.notifs.forEach(notif => this.notifQueue.next(notif)); this.notifs = []; return s; } - } diff --git a/src/angular/notifications/utilities/notification.config.ts b/src/angular/notifications/utilities/notification.config.ts index f469b7d..d10ce02 100644 --- a/src/angular/notifications/utilities/notification.config.ts +++ b/src/angular/notifications/utilities/notification.config.ts @@ -1,18 +1,18 @@ import { Type, ComponentRef } from '@angular/core'; export type NotificationType = - "info" | "warn" | "error" | "success"; + "info" | "warning" | "error" | "success"; export class NotificationSettings { - + public type: NotificationType; public notifyText: string; public notifyTitle: string; public sticky: boolean; - public hasCustomContent :boolean; - public duration:number; + public hasCustomContent: boolean; + public duration: number; public innerComponentType: Type<any>; - public innerComponentOptions : any; + public innerComponentOptions: any; constructor(type: NotificationType, notifyText: string, notifyTitle: string, duration: number = 10000, sticky: boolean = false, hasCustomContent:boolean = false, innerComponentType?:Type<any>, innerComponentOptions? :any) { diff --git a/src/angular/polyfills.ts b/src/angular/polyfills.ts new file mode 100644 index 0000000..fbd11b8 --- /dev/null +++ b/src/angular/polyfills.ts @@ -0,0 +1,67 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +// import 'core-js/es6/symbol'; +// import 'core-js/es6/object'; +// import 'core-js/es6/function'; +// import 'core-js/es6/parse-int'; +// import 'core-js/es6/parse-float'; +// import 'core-js/es6/number'; +// import 'core-js/es6/math'; +// import 'core-js/es6/string'; +// import 'core-js/es6/date'; +// import 'core-js/es6/array'; +// import 'core-js/es6/regexp'; +// import 'core-js/es6/map'; +// import 'core-js/es6/weak-map'; +// import 'core-js/es6/set'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** Evergreen browsers require these. **/ +import 'core-js/es6/reflect'; +import 'core-js/es7/reflect'; + +/** + * Required to support Web Animations `@angular/animation`. + * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation + **/ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/*************************************************************************************************** + * Zone JS is required by Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ + +/** + * Date, currency, decimal and percent pipes. + * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 + */ +// import 'intl'; // Run `npm install --save intl`. +/** + * Need to import at least one locale-data with intl. + */ +// import 'intl/locale-data/jsonp/en'; diff --git a/src/angular/popup-menu/popup-menu-item.component.spec.ts b/src/angular/popup-menu/popup-menu-item.component.spec.ts index 25b2694..8454317 100644 --- a/src/angular/popup-menu/popup-menu-item.component.spec.ts +++ b/src/angular/popup-menu/popup-menu-item.component.spec.ts @@ -1,7 +1,4 @@ -import { Component, Input, Output, ContentChildren, SimpleChanges, QueryList, EventEmitter, OnChanges, AfterContentInit } from '@angular/core'; -import { FormsModule } from "@angular/forms"; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { PopupMenuItemComponent } from './popup-menu-item.component'; import { PopupMenuListComponent } from './popup-menu-list.component'; describe('Popup Menu', () => { diff --git a/src/angular/popup-menu/popup-menu.module.ts b/src/angular/popup-menu/popup-menu.module.ts index 3a58b91..03559f2 100644 --- a/src/angular/popup-menu/popup-menu.module.ts +++ b/src/angular/popup-menu/popup-menu.module.ts @@ -3,7 +3,6 @@ import { PopupMenuListComponent } from "./popup-menu-list.component"; import { PopupMenuItemComponent } from "./popup-menu-item.component"; import { CommonModule } from "@angular/common"; - @NgModule({ declarations: [ PopupMenuListComponent, diff --git a/src/angular/searchbar/search-bar.component.html.ts b/src/angular/searchbar/search-bar.component.html.ts index 79153f4..5d10a87 100644 --- a/src/angular/searchbar/search-bar.component.html.ts +++ b/src/angular/searchbar/search-bar.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="search-bar-container" [ngClass]="{'not-empty': searchQuery}"> <sdc-input class="sdc-input-wrapper" [label]="label" diff --git a/src/angular/searchbar/search-bar.component.ts b/src/angular/searchbar/search-bar.component.ts index 7f508d7..42dfaeb 100644 --- a/src/angular/searchbar/search-bar.component.ts +++ b/src/angular/searchbar/search-bar.component.ts @@ -1,5 +1,5 @@ import { Component, Input, Output, EventEmitter, HostBinding } from '@angular/core'; -import template from "./search-bar.component.html"; +import { template } from "./search-bar.component.html"; @Component({ selector: 'sdc-search-bar', @@ -11,9 +11,14 @@ export class SearchBarComponent { @Input() public placeholder: string; @Input() public label: string; @Input() public searchQuery: string; + @Input() public debounceTime: number; @Output() public searchQueryClick: EventEmitter<string> = new EventEmitter<string>(); - private searchButtonClick = (): void => { - this.searchQueryClick.emit(this.searchQuery); + // constructor() { + // this.debounceTime = 200; + // } + + public searchButtonClick = (): void => { + this.searchQueryClick.emit(this.searchQuery); } } diff --git a/src/angular/services.ts b/src/angular/services.ts new file mode 100644 index 0000000..65d5918 --- /dev/null +++ b/src/angular/services.ts @@ -0,0 +1,13 @@ +/* + Exports all the services of onap-ui-angular. + */ + +// Modals +export { ModalService } from "./modals/modal.service"; + +// Loader +export { LoaderService } from './loader/loader.service'; + +// Notifications +export { NotificationsService } from "./notifications/services/notifications.service"; + diff --git a/src/angular/styles.css b/src/angular/styles.css new file mode 100644 index 0000000..1d04302 --- /dev/null +++ b/src/angular/styles.css @@ -0,0 +1,9 @@ +/* You can add global styles to this file, and also import other style files */ + +.green-color { + color: green; +} + +.css-rules-warning { + display: none; +} diff --git a/src/angular/svg-icon/svg-icon-label.component.html.ts b/src/angular/svg-icon/svg-icon-label.component.html.ts index 558b7c4..7925739 100644 --- a/src/angular/svg-icon/svg-icon-label.component.html.ts +++ b/src/angular/svg-icon/svg-icon-label.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="svg-icon-wrapper" [ngClass]="[(mode) ? 'mode-'+mode : '', (size) ? 'size-'+size : '', (labelPlacement) ? 'label-placement-'+labelPlacement : '', (clickable) ? 'clickable' : '', className || '']" [attr.disabled]="disabled || undefined"> <svg-icon [name]="name" className="svg-icon"></svg-icon> <span class="svg-icon-label" [ngClass]="[labelClassName || '']">{{ label }}</span> diff --git a/src/angular/svg-icon/svg-icon-label.component.ts b/src/angular/svg-icon/svg-icon-label.component.ts index 5a00c3d..c4cdae1 100644 --- a/src/angular/svg-icon/svg-icon-label.component.ts +++ b/src/angular/svg-icon/svg-icon-label.component.ts @@ -1,8 +1,8 @@ import { Component, Input } from "@angular/core"; import { SvgIconComponent } from './svg-icon.component'; -import { Mode, Size, Placement } from "../common/enums"; +import { Placement } from "../common/enums"; import { DomSanitizer, SafeHtml } from "@angular/platform-browser"; -import template from './svg-icon-label.component.html'; +import { template } from './svg-icon-label.component.html'; @Component({ selector: 'svg-icon-label', diff --git a/src/angular/svg-icon/svg-icon.component.html.ts b/src/angular/svg-icon/svg-icon.component.html.ts index 1baedbd..a991ed3 100644 --- a/src/angular/svg-icon/svg-icon.component.html.ts +++ b/src/angular/svg-icon/svg-icon.component.html.ts @@ -1,3 +1,3 @@ -export default ` +export const template = ` <div [ngClass]="classes" [attr.disabled]="disabled || undefined" [innerHtml]="svgIconContentSafeHtml"></div> `; diff --git a/src/angular/svg-icon/svg-icon.component.ts b/src/angular/svg-icon/svg-icon.component.ts index d53981d..f41b206 100644 --- a/src/angular/svg-icon/svg-icon.component.ts +++ b/src/angular/svg-icon/svg-icon.component.ts @@ -1,8 +1,8 @@ import { Component, Input, OnChanges, SimpleChanges, HostBinding } from "@angular/core"; import { DomSanitizer, SafeHtml } from "@angular/platform-browser"; -import { Mode, Size } from "../common/enums"; -import iconsMap from '../../common/icons-map'; -import template from './svg-icon.component.html'; +import { Mode, Size, BackgroundShape, BackgroundColor } from "../common/enums"; +import { iconsMap } from 'onap-ui-common'; +import { template } from './svg-icon.component.html'; @Component({ selector: 'svg-icon', @@ -16,35 +16,37 @@ import template from './svg-icon.component.html'; export class SvgIconComponent implements OnChanges { @Input() public name: string; + @Input() public category: string; @Input() public mode: Mode; @Input() public size: Size; + @Input() public backgroundShape: BackgroundShape; + @Input() public backgroundColor: BackgroundColor; @Input() public disabled: boolean; @Input() public clickable: boolean; @Input() public className: any; - + public svgIconContent: string; public svgIconContentSafeHtml: SafeHtml; public svgIconCustomClassName: string; - private classes: string; + public classes: string; constructor(protected domSanitizer: DomSanitizer) { this.size = Size.medium; this.disabled = false; + this.category = this.category || "common"; } - static get Icons(): {[key: string]: string} { + static Icons(): { [key: string]: string } { return iconsMap; } public ngOnChanges(changes: SimpleChanges) { - if (changes.name) { - this.updateSvgIconByName(); - this.buildClasses(); - } + this.updateSvgIconByName(); + this.buildClasses(); } protected updateSvgIconByName() { - this.svgIconContent = SvgIconComponent.Icons[this.name] || null; + this.svgIconContent = iconsMap[this.category][this.name] || null; if (this.svgIconContent) { this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.svgIconContent); this.svgIconCustomClassName = '__' + this.name.replace(/\s+/g, '_'); @@ -55,22 +57,17 @@ export class SvgIconComponent implements OnChanges { } private buildClasses = (): void => { - const _classes = []; - _classes.push('svg-icon'); - if (this.mode) { - _classes.push('mode-' + this.mode); - } - if (this.size) { - _classes.push('size-' + this.size); - } - if (this.clickable) { - _classes.push('clickable'); - } - if (this.svgIconCustomClassName) { - _classes.push(this.svgIconCustomClassName); - } - if (this.className) { - _classes.push(this.className); + const _classes = ['svg-icon']; + if (this.mode) { _classes.push('mode-' + this.mode); } + if (this.size) { _classes.push('size-' + this.size); } + if (this.clickable) { _classes.push('clickable'); } + if (this.svgIconCustomClassName) { _classes.push(this.svgIconCustomClassName); } + if (this.className) { _classes.push(this.className); } + if (this.backgroundShape) { _classes.push('bg-type-' + this.backgroundShape); } + if (this.backgroundShape && this.backgroundColor) { + _classes.push('bg-color-' + this.backgroundColor); + } else if (this.backgroundShape && !this.backgroundColor) { + _classes.push('bg-color-primary'); } this.classes = _classes.join(" "); } diff --git a/src/angular/tabs/children/tab.component.html.ts b/src/angular/tabs/children/tab.component.html.ts index 36ff413..cff7a8c 100644 --- a/src/angular/tabs/children/tab.component.html.ts +++ b/src/angular/tabs/children/tab.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div [hidden]="!active" class="sdc-tab-content" role="tabpanel"> <ng-content></ng-content> </div> diff --git a/src/angular/tabs/children/tab.component.ts b/src/angular/tabs/children/tab.component.ts index 3b96e87..a289aab 100644 --- a/src/angular/tabs/children/tab.component.ts +++ b/src/angular/tabs/children/tab.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core'; import { Mode } from './../../common/enums'; -import template from "./tab.component.html"; +import { template } from "./tab.component.html"; @Component({ selector: 'sdc-tab', diff --git a/src/angular/tabs/tabs.component.html.ts b/src/angular/tabs/tabs.component.html.ts index 2333b86..ac82dd6 100644 --- a/src/angular/tabs/tabs.component.html.ts +++ b/src/angular/tabs/tabs.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <ul class="sdc-tabs-list" role="tablist"> <li *ngFor="let tab of tabs" class="sdc-tab" role="tab" (click)="selectTab(tab)" [class.sdc-tab-active]="tab.active"> <span *ngIf="tab.title">{{tab.title}}</span> diff --git a/src/angular/tabs/tabs.component.ts b/src/angular/tabs/tabs.component.ts index 595f304..c3b6507 100644 --- a/src/angular/tabs/tabs.component.ts +++ b/src/angular/tabs/tabs.component.ts @@ -1,8 +1,7 @@ -import { Component, Input, AfterContentInit, ContentChildren, QueryList, HostBinding } from '@angular/core'; +import { Component, Input, AfterContentInit, ContentChildren, QueryList, HostBinding, EventEmitter, Output } from '@angular/core'; import { TabComponent } from './children/tab.component'; -import { SvgIconComponent } from "./../../../src/angular/svg-icon/svg-icon.component"; -import { Mode, Placement, Size } from './../common/enums'; -import template from "./tabs.component.html"; +import { Mode, Size } from './../common/enums'; +import { template } from "./tabs.component.html"; @Component({ selector: 'sdc-tabs', @@ -12,20 +11,22 @@ import template from "./tabs.component.html"; export class TabsComponent implements AfterContentInit { @HostBinding('class') classes = 'sdc-tabs sdc-tabs-header'; - @ContentChildren(TabComponent) private tabs: QueryList<TabComponent>; + @ContentChildren(TabComponent) public tabs: QueryList<TabComponent>; + @Output() public selectedTab: EventEmitter<TabComponent> = new EventEmitter<TabComponent>(); public _size = Size.medium; public selectTab(tab: TabComponent) { - // deactivate all tabs - this.tabs.toArray().forEach((_tab: TabComponent) => { - _tab.active = false; - _tab.titleIconMode = Mode.secondary; - }); - - // activate the tab the user has clicked on. - tab.active = true; - tab.titleIconMode = Mode.primary; + this.selectedTab.emit(tab); + // deactivate all tabs + this.tabs.toArray().forEach((_tab: TabComponent) => { + _tab.active = false; + _tab.titleIconMode = Mode.secondary; + }); + + // activate the tab the user has clicked on. + tab.active = true; + tab.titleIconMode = Mode.primary; } public ngAfterContentInit() { @@ -38,4 +39,4 @@ export class TabsComponent implements AfterContentInit { } } - } +} diff --git a/src/angular/tabs/tabs.module.ts b/src/angular/tabs/tabs.module.ts index 107942d..6b42c0e 100644 --- a/src/angular/tabs/tabs.module.ts +++ b/src/angular/tabs/tabs.module.ts @@ -1,6 +1,5 @@ import { NgModule } from "@angular/core"; import { CommonModule } from "@angular/common"; -import { FormElementsModule } from "../form-elements/form-elements.module"; import { TabsComponent } from "./tabs.component"; import { TabComponent } from './children/tab.component'; import { SvgIconModule } from './../svg-icon/svg-icon.module'; diff --git a/src/angular/tag-cloud/tag-cloud.component.html.ts b/src/angular/tag-cloud/tag-cloud.component.html.ts index 2ff4e8a..f3439e6 100644 --- a/src/angular/tag-cloud/tag-cloud.component.html.ts +++ b/src/angular/tag-cloud/tag-cloud.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="sdc-tag-cloud-new-item-field" [ngClass]="{'not-empty': newTagItem}"> <sdc-input [label]="label" [disabled]="(isViewOnly===true)" diff --git a/src/angular/tag-cloud/tag-cloud.component.ts b/src/angular/tag-cloud/tag-cloud.component.ts index 1635b8d..b7a2fec 100644 --- a/src/angular/tag-cloud/tag-cloud.component.ts +++ b/src/angular/tag-cloud/tag-cloud.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import template from "./tag-cloud.component.html"; +import { template } from "./tag-cloud.component.html"; @Component({ selector: 'sdc-tag-cloud', @@ -7,22 +7,22 @@ import template from "./tag-cloud.component.html"; }) export class TagCloudComponent { @Input() public list: string[]; - @Input() public isViewOnly: boolean|number[]; // get a boolean parameter or array of specific items indexes. + @Input() public isViewOnly: boolean | number[]; // get a boolean parameter or array of specific items indexes. @Input() public isUniqueList: boolean; @Input() public uniqueErrorMessage: string = "Unique error"; @Input() public label: string; @Input() public placeholder: string; @Output() public listChanged: EventEmitter<string[]> = new EventEmitter<string[]>(); - private newTagItem: string; - private uniqueError: boolean; + public newTagItem: string; + public uniqueError: boolean; - private onKeyup = (e): void => { + public onKeyup = (e): void => { if (e.keyCode === 13) { this.insertItemToList(); } } - private insertItemToList = (): void => { + public insertItemToList = (): void => { this.validateTag(); if (!this.uniqueError && this.newTagItem.length) { this.list.push(this.newTagItem); diff --git a/src/angular/tag-cloud/tag-item/tag-item.component.html.ts b/src/angular/tag-cloud/tag-item/tag-item.component.html.ts index 04112c1..db0e115 100644 --- a/src/angular/tag-cloud/tag-item/tag-item.component.html.ts +++ b/src/angular/tag-cloud/tag-item/tag-item.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <div class="tag-item" [ngClass]="{'view-only':isViewOnly}"> <span>{{text}}</span> <span class="delete-item" *ngIf="!isViewOnly" (click)="clickOnDelete.emit(index)"> diff --git a/src/angular/tag-cloud/tag-item/tag-item.component.ts b/src/angular/tag-cloud/tag-item/tag-item.component.ts index f2e2fa7..7da8f36 100644 --- a/src/angular/tag-cloud/tag-item/tag-item.component.ts +++ b/src/angular/tag-cloud/tag-item/tag-item.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Input, Output, HostBinding } from "@angular/core"; -import template from "./tag-item.component.html"; +import { template } from "./tag-item.component.html"; @Component({ selector: 'sdc-tag-item', diff --git a/src/angular/test.ts b/src/angular/test.ts new file mode 100644 index 0000000..fe4ee8c --- /dev/null +++ b/src/angular/test.ts @@ -0,0 +1,29 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/long-stack-trace-zone'; +import 'zone.js/dist/proxy.js'; +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/jasmine-patch'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; + +// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. +declare const __karma__: any; +declare const require: any; + +// Prevent Karma from running prematurely. +__karma__.loaded = function() {}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); +// Finally, start Karma to run the tests. +__karma__.start(); diff --git a/src/angular/tiles/tile.component.html.ts b/src/angular/tiles/tile.component.html.ts index 81803d5..2e96b42 100644 --- a/src/angular/tiles/tile.component.html.ts +++ b/src/angular/tiles/tile.component.html.ts @@ -1,4 +1,4 @@ -export default ` +export const template = ` <ng-content select="sdc-tile-header"></ng-content> <ng-content select="sdc-tile-content"></ng-content> <ng-content select="sdc-tile-footer"></ng-content> diff --git a/src/angular/tiles/tile.component.ts b/src/angular/tiles/tile.component.ts index 3791ca0..6379294 100644 --- a/src/angular/tiles/tile.component.ts +++ b/src/angular/tiles/tile.component.ts @@ -1,5 +1,5 @@ import { Component, HostBinding } from '@angular/core'; -import template from "./tile.component.html"; +import { template } from "./tile.component.html"; @Component({ selector: "sdc-tile", diff --git a/src/angular/tooltip/tooltip.directive.ts b/src/angular/tooltip/tooltip.directive.ts index 77cec62..5489657 100644 --- a/src/angular/tooltip/tooltip.directive.ts +++ b/src/angular/tooltip/tooltip.directive.ts @@ -192,7 +192,7 @@ export class TooltipDirective implements OnInit { * @returns {IPlacementData} */ private getPlacement(placement: TooltipPlacement, - ...additionalPlacements: TooltipPlacement[], + ...additionalPlacements: TooltipPlacement[] ): IPlacementData { const placements: TooltipPlacement[] = [placement, ...additionalPlacements]; const filterPlacements = placements diff --git a/src/angular/tooltip/tooltip.module.ts b/src/angular/tooltip/tooltip.module.ts index a4ad86d..8911008 100644 --- a/src/angular/tooltip/tooltip.module.ts +++ b/src/angular/tooltip/tooltip.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { TooltipDirective } from './tooltip.directive'; import { TooltipTemplateComponent } from './tooltip-template.component'; +import { CreateDynamicComponentService } from '../utils/create-dynamic-component.service'; @NgModule({ declarations: [ @@ -12,6 +13,7 @@ import { TooltipTemplateComponent } from './tooltip-template.component'; exports: [ TooltipDirective ], + providers: [CreateDynamicComponentService] }) export class TooltipModule { } diff --git a/src/angular/tsconfig.app.json b/src/angular/tsconfig.app.json new file mode 100644 index 0000000..dafdb9b --- /dev/null +++ b/src/angular/tsconfig.app.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/app", + "baseUrl": "./", + "module": "es2015", + "types": [ + "node" + ] + }, + "exclude": [ + "test.ts", + "**/*.spec.ts" + ] +} diff --git a/src/angular/tsconfig.spec.json b/src/angular/tsconfig.spec.json new file mode 100644 index 0000000..c5d30ee --- /dev/null +++ b/src/angular/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "baseUrl": "./", + "module": "commonjs", + "target": "es5", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/src/angular/typings.d.ts b/src/angular/typings.d.ts new file mode 100644 index 0000000..b58fa33 --- /dev/null +++ b/src/angular/typings.d.ts @@ -0,0 +1,10 @@ +/* SystemJS module definition */ +declare var module: NodeModule; +interface NodeModule { + id: string; +} + +declare module '*.json' { + const value: any; + export default value; +} diff --git a/src/angular/utils/create-dynamic-component.service.ts b/src/angular/utils/create-dynamic-component.service.ts index 428dd73..506f787 100644 --- a/src/angular/utils/create-dynamic-component.service.ts +++ b/src/angular/utils/create-dynamic-component.service.ts @@ -17,8 +17,7 @@ export class CreateDynamicComponentService { * @memberOf InjectionService */ private getRootViewContainer(): ComponentRef<any> { - const rootComponents = this.applicationRef['_rootComponents']; // Angular2 - // const rootComponents = this.applicationRef['components']; // Angular5 + const rootComponents = this.applicationRef['components']; if (rootComponents.length) { return rootComponents[0]; } |