From 740fd6b403faca0744ce004039df859ee17f1508 Mon Sep 17 00:00:00 2001 From: theoriginaljosh Date: Fri, 28 Oct 2016 13:25:41 -0400 Subject: [PATCH 1/9] adding warning to base inputs for ng2 and ng1 --- source/components/inputs/input.ng1.ts | 2 ++ source/components/inputs/input.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/source/components/inputs/input.ng1.ts b/source/components/inputs/input.ng1.ts index 47940398..1afce1e2 100644 --- a/source/components/inputs/input.ng1.ts +++ b/source/components/inputs/input.ng1.ts @@ -44,6 +44,7 @@ export class InputController { validators: __validation.IValidationHandler[]; label: string; name: string; + warning: boolean; ngModel: INgModelValidator; required: RequiredController; @@ -109,6 +110,7 @@ let baseInputOptions: angular.IComponentOptions = { validators: ' implements AfterViewInit, OnInit { name: string; label: string = ''; disabled: boolean; + warning: boolean; value: T; change: EventEmitter = new EventEmitter(); valueChange: EventEmitter = this.change; From 6dcdeeb1fee9fe662329f68616b6bc7b6736820c Mon Sep 17 00:00:00 2001 From: theoriginaljosh Date: Fri, 28 Oct 2016 13:26:23 -0400 Subject: [PATCH 2/9] Adding warning class to textbox n2 and ng1 inputs --- source/components/inputs/textbox/textbox.html | 3 ++- source/components/inputs/textbox/textbox.ng1.html | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/components/inputs/textbox/textbox.html b/source/components/inputs/textbox/textbox.html index 3177ce65..59110d0e 100644 --- a/source/components/inputs/textbox/textbox.html +++ b/source/components/inputs/textbox/textbox.html @@ -1,5 +1,6 @@
+ [class.error]="!control.valid" + [class.warning]="!!control.warning"> +
{{input.inputValidator.error}} From 344c761c6a52b08a2b81647413ecbd0daa0ffb7a Mon Sep 17 00:00:00 2001 From: theoriginaljosh Date: Fri, 28 Oct 2016 13:26:50 -0400 Subject: [PATCH 3/9] temp --- bootstrapper/inputs/inputsNg1.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrapper/inputs/inputsNg1.html b/bootstrapper/inputs/inputsNg1.html index 300815aa..8a602a19 100644 --- a/bootstrapper/inputs/inputsNg1.html +++ b/bootstrapper/inputs/inputsNg1.html @@ -88,7 +88,7 @@

Required input: - +

From 997fdd361afa6b090a0c86cb4375cc5756677b11 Mon Sep 17 00:00:00 2001 From: theoriginaljosh Date: Fri, 28 Oct 2016 13:29:54 -0400 Subject: [PATCH 4/9] merge conflict --- bootstrapper/app.html | 22 ++-- bootstrapper/app.ng2.ts | 12 ++ bootstrapper/app.routing.ts | 102 ++++++++++++++ bootstrapper/app.ts | 113 +++++++++++----- bootstrapper/bootstrapper.css | 7 + bootstrapper/buttons/buttonBootstrapper.ts | 45 +++---- bootstrapper/buttons/buttonRoot.ts | 7 + bootstrapper/buttons/buttons.html | 6 +- bootstrapper/buttons/buttonsNg2.html | 5 + .../cards/cardContainerBootstrapper.ts | 32 ++--- bootstrapper/cards/cardRoot.ts | 7 + bootstrapper/cards/cards.html | 6 +- bootstrapper/forms/forms.html | 6 +- bootstrapper/forms/formsBootstrapper.ts | 32 ++--- bootstrapper/forms/formsNg2.html | 4 +- bootstrapper/forms/formsNg2Bootstrapper.ts | 17 ++- bootstrapper/forms/formsRoot.ts | 7 + bootstrapper/inputs/inputBootstrapper.ts | 32 ++--- bootstrapper/inputs/inputRoot.ts | 7 + bootstrapper/inputs/inputs.html | 6 +- bootstrapper/inputs/inputsNg2.html | 2 +- .../messageLog/messageLogBootstrapper.ts | 24 ++-- bootstrapper/messageLog/messageLogTest.html | 4 +- bootstrapper/misc/misc.html | 6 +- bootstrapper/misc/miscBootstrapper.ts | 45 +++---- bootstrapper/misc/miscNg1.html | 4 +- bootstrapper/misc/miscRoot.ts | 7 + bootstrapper/msi/msi.html | 5 - bootstrapper/msi/msi.ng1.html | 2 - bootstrapper/msi/msi.ng2.html | 14 +- bootstrapper/msi/msiBootstrapper.ng1.ts | 47 ------- bootstrapper/msi/msiBootstrapper.ng2.ts | 36 ++--- bootstrapper/popup/popup.html | 6 +- bootstrapper/popup/popupBootstrapper.ts | 32 ++--- bootstrapper/popup/popupNg2.html | 2 +- bootstrapper/popup/popupRoot.ts | 7 + bootstrapper/tabs/tabRoot.ts | 7 + bootstrapper/tabs/tabs.html | 6 +- bootstrapper/tabs/tabsBootstrapper.ts | 32 ++--- bootstrapper/tabs/tabsNg1.html | 2 - bootstrapper/text/text.ts | 14 +- bootstrapper/welcome.component.ts | 7 + index.html | 6 +- package.json | 32 ++--- source/animations/index.ts | 5 + source/animations/slide/slide.animate.ts | 17 +++ source/behaviors/autosave/autosave.tests.ts | 21 ++- source/behaviors/autosave/autosave.ts | 6 +- .../buttons/buttonRoute/buttonRoute.html | 7 + .../buttons/buttonRoute/buttonRoute.tests.ts | 18 +++ .../buttons/buttonRoute/buttonRoute.ts | 18 +++ source/components/buttons/index.ts | 5 +- .../cardContainer/cardContainer.ng1.html | 2 +- .../cardContainer/cardContainer.ng1.tests.ts | 21 --- .../cardContainer/cardContainer.ng1.ts | 4 - .../components/cardContainer/cardContainer.ts | 2 +- .../simpleDataSource.service.ts | 1 + source/components/components.module.ts | 5 +- source/components/dialog/dialog.tests.ts | 4 +- source/components/dialog/dialog.ts | 2 + source/components/dialog/dialogOutlet.html | 4 +- .../components/dialog/dialogOutlet.tests.ts | 22 +++- source/components/dialog/dialogOutlet.ts | 5 + .../components/dialog/dialogRoot.service.ts | 3 +- source/components/form/form.ts | 2 +- .../inputs/absoluteTime/absoluteTime.html | 15 ++- .../inputs/absoluteTime/absoluteTime.tests.ts | 5 +- .../inputs/absoluteTime/absoluteTime.ts | 3 + .../components/inputs/dateTime/dateTime.html | 13 +- source/components/inputs/dateTime/dateTime.ts | 15 ++- source/components/inputs/input.tests.ts | 48 +++++++ source/components/inputs/input.ts | 28 +++- source/components/inputs/select/select.html | 20 +-- .../components/inputs/select/select.ng1.html | 12 +- .../inputs/select/select.ng1.tests.ts | 7 +- source/components/inputs/select/select.ng1.ts | 6 +- .../components/inputs/select/select.tests.ts | 35 +---- source/components/inputs/select/select.ts | 12 +- .../inputs/signature/signature.tests.ts | 4 +- source/components/inputs/spinner/spinner.html | 21 +-- source/components/inputs/spinner/spinner.ts | 3 + .../components/inputs/textarea/textarea.html | 15 ++- source/components/inputs/textarea/textarea.ts | 3 + source/components/inputs/textbox/textbox.html | 15 ++- source/components/inputs/textbox/textbox.ts | 3 + .../inputs/typeahead/typeahead.html | 15 ++- .../inputs/typeahead/typeahead.tests.ts | 9 +- .../components/inputs/typeahead/typeahead.ts | 23 +++- .../typeaheadList/typeaheadList.tests.ts | 6 +- .../inputs/userRating/userRating.html | 10 +- .../inputs/userRating/userRating.tests.ts | 28 +++- .../inputs/userRating/userRating.ts | 16 ++- .../inputs/validationInput.tests.ts | 25 ++-- source/components/inputs/validationInput.ts | 22 ++-- .../messageLog/messageLog.directive.tests.ts | 1 + .../messageLog/messageLog.directive.ts | 16 ++- .../multiStepIndicator.ng1.html | 16 --- .../multiStepIndicator.ng1.ts | 124 ------------------ .../multiStepIndicator.tests.ng1.ts | 115 ---------------- .../multiStepIndicator.tests.ts | 58 ++++---- .../multiStepIndicator/multiStepIndicator.ts | 58 ++++---- .../multiStepIndicator/step.component.html | 8 ++ .../multiStepIndicator/step.component.ts | 19 +++ source/components/popoutList/popoutList.html | 6 +- .../components/popoutList/popoutList.tests.ts | 2 +- source/components/popoutList/popoutList.ts | 8 +- .../validationGroup/validationGroup.html | 4 +- .../validationGroup/validationGroup.tests.ts | 21 ++- .../validationGroup/validationGroup.ts | 11 +- source/componentsDowngrade.ts | 5 +- .../autosaveAction.service.tests.ts | 28 ++-- .../autosaveAction/autosaveAction.service.ts | 56 ++++---- .../componentValidator.service.tests.ts | 71 ++++------ .../componentValidator.service.ts | 47 +++---- source/ui.module.ts | 6 +- system.config.js | 4 +- 116 files changed, 1098 insertions(+), 1021 deletions(-) create mode 100644 bootstrapper/app.ng2.ts create mode 100644 bootstrapper/app.routing.ts create mode 100644 bootstrapper/bootstrapper.css create mode 100644 bootstrapper/buttons/buttonRoot.ts create mode 100644 bootstrapper/cards/cardRoot.ts create mode 100644 bootstrapper/forms/formsRoot.ts create mode 100644 bootstrapper/inputs/inputRoot.ts create mode 100644 bootstrapper/misc/miscRoot.ts delete mode 100644 bootstrapper/msi/msi.html delete mode 100644 bootstrapper/msi/msi.ng1.html delete mode 100644 bootstrapper/msi/msiBootstrapper.ng1.ts create mode 100644 bootstrapper/popup/popupRoot.ts create mode 100644 bootstrapper/tabs/tabRoot.ts create mode 100644 bootstrapper/welcome.component.ts create mode 100644 source/animations/index.ts create mode 100644 source/animations/slide/slide.animate.ts create mode 100644 source/components/buttons/buttonRoute/buttonRoute.html create mode 100644 source/components/buttons/buttonRoute/buttonRoute.tests.ts create mode 100644 source/components/buttons/buttonRoute/buttonRoute.ts delete mode 100644 source/components/multiStepIndicator/multiStepIndicator.ng1.html delete mode 100644 source/components/multiStepIndicator/multiStepIndicator.ng1.ts delete mode 100644 source/components/multiStepIndicator/multiStepIndicator.tests.ng1.ts create mode 100644 source/components/multiStepIndicator/step.component.html create mode 100644 source/components/multiStepIndicator/step.component.ts diff --git a/bootstrapper/app.html b/bootstrapper/app.html index 0d40c15a..ac7e6be7 100644 --- a/bootstrapper/app.html +++ b/bootstrapper/app.html @@ -1,20 +1,20 @@ diff --git a/bootstrapper/app.ng2.ts b/bootstrapper/app.ng2.ts new file mode 100644 index 00000000..ca9783f5 --- /dev/null +++ b/bootstrapper/app.ng2.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'ts-app', + template: require('./app.html'), +}) +export class App { + constructor(router: Router) { + router['initialNavigation'](); + } +} diff --git a/bootstrapper/app.routing.ts b/bootstrapper/app.routing.ts new file mode 100644 index 00000000..672e133c --- /dev/null +++ b/bootstrapper/app.routing.ts @@ -0,0 +1,102 @@ +import { ModuleWithProviders } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +import { WelcomeComponent } from './welcome.component' +import { InputsRootComponent } from './inputs/inputRoot'; +import { InputsNg1BootstrapperComponent } from './inputs/inputBootstrapper'; +import { InputsBootstrapper } from './inputs/inputsNg2Bootstrapper'; +import { ButtonsNg1BootstrapperComponent, ButtonsNg2BootstrapperComponent } from './buttons/buttonBootstrapper'; +import { ButtonsRootComponent } from './buttons/buttonRoot'; +import { PopupRootComponent } from './popup/popupRoot'; +import { PopupNg1BootstrapperComponent } from './popup/popupBootstrapper'; +import { PopupBootstrapper } from './popup/popupNg2Bootstrapper'; +import { CardsRootComponent } from './cards/cardRoot'; +import { CardsNg1BootstrapperComponent } from './cards/cardContainerBootstrapper'; +import { CardsBootstrapper } from './cards/cardsNg2Bootstrapper'; +import { TabsRootComponent } from './tabs/tabRoot'; +import { TabsNg1BootstrapperComponent } from './tabs/tabsBootstrapper'; +import { TabsBootstrapper } from './tabs/tabsNg2Bootstrapper'; +import { MsiBootstrapperComponent } from './msi/msiBootstrapper.ng2'; +import { FormsRootComponent } from './forms/formsRoot'; +import { FormsNg1BootstrapperComponent } from './forms/formsBootstrapper'; +import { FormsBootstrapper } from './forms/formsNg2Bootstrapper'; +import { MessageLogNg1BootstrapperComponent } from './messageLog/messageLogBootstrapper'; +import { MiscRootComponent } from './misc/miscRoot'; +import { MiscNgContextBootstrapper } from './misc/miscNg2Context'; +import { MiscNg1BootstrapperComponent, MiscNg2BootstrapperComponent } from './misc/miscBootstrapper'; + +const appRoutes: Routes = [ + { path: '', component: WelcomeComponent }, + { + path: 'inputs', + component: InputsRootComponent, + children: [ + { path: 'ng1', component: InputsNg1BootstrapperComponent }, + { path: 'ng2', component: InputsBootstrapper }, + ], + }, + { + path: 'buttons', + component: ButtonsRootComponent, + children: [ + { path: 'ng1', component: ButtonsNg1BootstrapperComponent }, + { path: 'ng2', component: ButtonsNg2BootstrapperComponent }, + ], + }, + { + path: 'popup', + component: PopupRootComponent, + children: [ + { path: 'ng1', component: PopupNg1BootstrapperComponent }, + { path: 'ng2', component: PopupBootstrapper }, + ], + }, + { + path: 'cards', + component: CardsRootComponent, + children: [ + { path: 'ng1', component: CardsNg1BootstrapperComponent }, + { path: 'ng2', component: CardsBootstrapper }, + ], + }, + { + path: 'tabs', + component: TabsRootComponent, + children: [ + { path: 'ng1', component: TabsNg1BootstrapperComponent }, + { path: 'ng2', component: TabsBootstrapper }, + ], + }, + { + path: 'msi', + children: [ + { path: 'ng2', component: MsiBootstrapperComponent }, + ], + }, + { + path: 'forms', + component: FormsRootComponent, + children: [ + { path: 'ng1', component: FormsNg1BootstrapperComponent }, + { path: 'ng2', component: FormsBootstrapper }, + ], + }, + { + path: 'messageLog', + component: MessageLogNg1BootstrapperComponent, + }, + { + path: 'misc', + component: MiscRootComponent, + children: [ + { path: 'ng1', component: MiscNg1BootstrapperComponent }, + { path: 'ng2', component: MiscNg2BootstrapperComponent }, + ], + }, +]; + +export const appRoutingProviders: any[] = [ + +]; + +export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); diff --git a/bootstrapper/app.ts b/bootstrapper/app.ts index 48d37cf7..71cef92d 100644 --- a/bootstrapper/app.ts +++ b/bootstrapper/app.ts @@ -1,9 +1,8 @@ import 'jquery'; import 'bootstrap'; import * as angular from 'angular'; -import 'angular-ui-router'; -import { NgModule, forwardRef } from '@angular/core'; +import { NgModule, forwardRef, ApplicationRef } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { UpgradeAdapter } from '@angular/upgrade'; @@ -18,18 +17,36 @@ import { moduleName as popupModuleName } from './popup/popupBootstrapper'; import { moduleName as messageLogModuleName } from './messageLog/messageLogBootstrapper'; import { moduleName as cardModuleName } from './cards/cardContainerBootstrapper'; import { moduleName as tabModuleName } from './tabs/tabsBootstrapper'; -import { moduleName as multStepModuleName } from './msi/msiBootstrapper.ng1'; import { moduleName as formModuleName } from './forms/formsBootstrapper'; import { moduleName as miscModuleName } from './misc/miscBootstrapper'; import { moduleName as textModuleName } from './text/text'; -import { TabsBootstrapper } from './tabs/tabsNg2Bootstrapper'; +import { WelcomeComponent } from './welcome.component'; +import { InputsRootComponent } from './inputs/inputRoot'; +import { InputsNg1BootstrapperComponent } from './inputs/inputBootstrapper'; import { InputsBootstrapper } from './inputs/inputsNg2Bootstrapper'; -import { FormsBootstrapper } from './forms/formsNg2Bootstrapper'; -import { MsiBootstrapperComponent } from './msi/msiBootstrapper.ng2'; -import { CardsBootstrapper } from './cards/cardsNg2Bootstrapper'; +import { ButtonsNg1BootstrapperComponent, ButtonsNg2BootstrapperComponent } from './buttons/buttonBootstrapper'; +import { ButtonsRootComponent } from './buttons/buttonRoot'; +import { PopupRootComponent } from './popup/popupRoot'; +import { PopupNg1BootstrapperComponent } from './popup/popupBootstrapper'; import { PopupBootstrapper } from './popup/popupNg2Bootstrapper'; +import { CardsRootComponent } from './cards/cardRoot'; +import { CardsNg1BootstrapperComponent } from './cards/cardContainerBootstrapper'; +import { CardsBootstrapper } from './cards/cardsNg2Bootstrapper'; +import { TabsRootComponent } from './tabs/tabRoot'; +import { TabsNg1BootstrapperComponent } from './tabs/tabsBootstrapper'; +import { TabsBootstrapper } from './tabs/tabsNg2Bootstrapper'; +import { MsiBootstrapperComponent } from './msi/msiBootstrapper.ng2'; +import { FormsRootComponent } from './forms/formsRoot'; +import { FormsNg1BootstrapperComponent } from './forms/formsBootstrapper'; +import { FormsBootstrapper } from './forms/formsNg2Bootstrapper'; +import { MessageLogNg1BootstrapperComponent } from './messageLog/messageLogBootstrapper'; +import { MiscRootComponent } from './misc/miscRoot'; import { MiscNgContextBootstrapper } from './misc/miscNg2Context'; +import { MiscNg1BootstrapperComponent, MiscNg2BootstrapperComponent } from './misc/miscBootstrapper'; +import { App } from './app.ng2'; + +import { appRoutingProviders, routing } from './app.routing'; import { ComponentsModule } from'../source/ui.module'; @@ -37,64 +54,88 @@ const upgradeAdapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Compo utilitiesDowngrade.downgradeUtilitiesToAngular1(upgradeAdapter); componentsDowngrade.downgradeComponentsToAngular1(upgradeAdapter); -const bootstrapper: angular.IComponentOptions = { - template: require('./app.html'), -} - const moduleName: string = 'bootstrapper-app'; angular.module(moduleName, [ componentsModule, - 'ui.router', utilitiesDowngrade.moduleName, - multStepModuleName, inputModuleName, buttonModuleName, popupModuleName, - messageLogModuleName, cardModuleName, tabModuleName, formModuleName, + messageLogModuleName, miscModuleName, textModuleName, ]) - .component('tsBootstrapper', bootstrapper) - .directive('tsInputsBootstrapper', upgradeAdapter.downgradeNg2Component(InputsBootstrapper)) - .directive('tsFormsBootstrapper', upgradeAdapter.downgradeNg2Component(FormsBootstrapper)) - .directive('tsTabsBootstrapper', upgradeAdapter.downgradeNg2Component(TabsBootstrapper)) - .directive('tsMsiBootstrapper', upgradeAdapter.downgradeNg2Component(MsiBootstrapperComponent)) - .directive('tsCardsBootstrapper', upgradeAdapter.downgradeNg2Component(CardsBootstrapper)) - .directive('tsPopupBootstrapper', upgradeAdapter.downgradeNg2Component(PopupBootstrapper)) - .directive('tsMiscNgContext', upgradeAdapter.downgradeNg2Component(MiscNgContextBootstrapper)) - .config(BaseRoute); + .directive('tsApp', upgradeAdapter.downgradeNg2Component(App)); @NgModule({ imports: [ BrowserModule, + routing, UtilitiesModule, ComponentsModule, ], declarations: [ InputsBootstrapper, - FormsBootstrapper, + InputsRootComponent, + InputsNg1BootstrapperComponent, + upgradeAdapter.upgradeNg1Component('tsInputsNg1'), + + ButtonsRootComponent, + ButtonsNg1BootstrapperComponent, + ButtonsNg2BootstrapperComponent, + upgradeAdapter.upgradeNg1Component('tsButtonsNg1'), + upgradeAdapter.upgradeNg1Component('tsButtonsNg2'), + + PopupRootComponent, + PopupNg1BootstrapperComponent, + PopupBootstrapper, + upgradeAdapter.upgradeNg1Component('tsPopupNg1'), + + CardsRootComponent, + CardsNg1BootstrapperComponent, + CardsBootstrapper, + upgradeAdapter.upgradeNg1Component('tsCardsNg1'), + + TabsRootComponent, + TabsNg1BootstrapperComponent, TabsBootstrapper, + upgradeAdapter.upgradeNg1Component('tsTabsNg1'), + MsiBootstrapperComponent, - CardsBootstrapper, - PopupBootstrapper, + + FormsRootComponent, + FormsNg1BootstrapperComponent, + FormsBootstrapper, + upgradeAdapter.upgradeNg1Component('tsFormsNg1'), + + MessageLogNg1BootstrapperComponent, + upgradeAdapter.upgradeNg1Component('tsMessageLogNg1'), + + MiscRootComponent, + MiscNg1BootstrapperComponent, + MiscNg2BootstrapperComponent, MiscNgContextBootstrapper, + upgradeAdapter.upgradeNg1Component('tsMiscNg1'), + upgradeAdapter.upgradeNg1Component('tsMiscNg2'), + + WelcomeComponent, + App, + ], + providers: [ + { + provide: ApplicationRef, + useValue: { + componentTypes: [App], + registerDisposeListener: () => {}, + }, + }, ], }) class ComponentsBootstrapperModule {} -BaseRoute.$inject = ['$urlRouterProvider', '$stateProvider']; -function BaseRoute($urlRouterProvider, $stateProvider) { - $urlRouterProvider.otherwise('/'); - $stateProvider - .state('/', { - url: '/', - template: '

Welcome to typescript-angular-components

', - }); -} - upgradeAdapter.bootstrap(document.body, [moduleName], { strictDI: true }); diff --git a/bootstrapper/bootstrapper.css b/bootstrapper/bootstrapper.css new file mode 100644 index 00000000..afb1a122 --- /dev/null +++ b/bootstrapper/bootstrapper.css @@ -0,0 +1,7 @@ +.rl-tab-item.error { + color: red; +} + +.rl-tab-item.current { + color: blue; +} diff --git a/bootstrapper/buttons/buttonBootstrapper.ts b/bootstrapper/buttons/buttonBootstrapper.ts index 923d80f8..237f2a3f 100644 --- a/bootstrapper/buttons/buttonBootstrapper.ts +++ b/bootstrapper/buttons/buttonBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; export const moduleName: string = 'ButtonTestModule'; @@ -19,27 +20,27 @@ class ButtonTestController { } } -ButtonRoute.$inject = ['$stateProvider']; -function ButtonRoute($stateProvider) { - $stateProvider - .state('buttons', { - url: '/buttons', - template: require('./buttons.html'), - }) - .state('buttons.ng1', { - url: '/ng1', - template: require('./buttonsNg1.html'), - controller: 'ButtonTestController', - controllerAs: 'button', - }) - .state('buttons.ng2', { - url: '/ng2', - template: require('./buttonsNg2.html'), - controller: 'ButtonTestController', - controllerAs: 'button', - }); -} +@Component({ + selector: 'tsButtonsNg1', + template: '' +}) +export class ButtonsNg1BootstrapperComponent { } + +@Component({ + selector: 'tsButtonsNg2', + template: '' +}) +export class ButtonsNg2BootstrapperComponent {} angular.module(moduleName, []) - .controller('ButtonTestController', ButtonTestController) - .config(ButtonRoute); + .component('tsButtonsNg1', { + template: require('./buttonsNg1.html'), + controller: 'ButtonTestController', + controllerAs: 'button', + }) + .component('tsButtonsNg2', { + template: require('./buttonsNg2.html'), + controller: 'ButtonTestController', + controllerAs: 'button', + }) + .controller('ButtonTestController', ButtonTestController); diff --git a/bootstrapper/buttons/buttonRoot.ts b/bootstrapper/buttons/buttonRoot.ts new file mode 100644 index 00000000..0d8e4edf --- /dev/null +++ b/bootstrapper/buttons/buttonRoot.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsButtonsRoot', + template: require('./buttons.html'), +}) +export class ButtonsRootComponent { } diff --git a/bootstrapper/buttons/buttons.html b/bootstrapper/buttons/buttons.html index 958ca287..7ac771d0 100644 --- a/bootstrapper/buttons/buttons.html +++ b/bootstrapper/buttons/buttons.html @@ -1,5 +1,5 @@ -
\ No newline at end of file + diff --git a/bootstrapper/buttons/buttonsNg2.html b/bootstrapper/buttons/buttonsNg2.html index ca5dcd9f..a72d79af 100644 --- a/bootstrapper/buttons/buttonsNg2.html +++ b/bootstrapper/buttons/buttonsNg2.html @@ -18,6 +18,11 @@

Link button

Large primary link button
Disabled link button
+
+

rlButtonRoute:

+
+
Route link button
+
Active route link button
diff --git a/bootstrapper/cards/cardContainerBootstrapper.ts b/bootstrapper/cards/cardContainerBootstrapper.ts index 7c5b44fa..8c69d577 100644 --- a/bootstrapper/cards/cardContainerBootstrapper.ts +++ b/bootstrapper/cards/cardContainerBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; import * as _ from 'lodash'; import * as moment from 'moment'; @@ -128,25 +129,16 @@ class CardTestController { } } -CardRoute.$inject = ['$stateProvider']; -function CardRoute($stateProvider) { - $stateProvider - .state('cards', { - url: '/cards', - template: require('./cards.html'), - }) - .state('cards.ng1', { - url: '/ng1', - template: require('./cardsNg1.html'), - controller: 'CardTestController', - controllerAs: 'cards', - }) - .state('cards.ng2', { - url: '/ng2', - template: '', - }); -} +@Component({ + selector: 'tsCardsNg1', + template: '' +}) +export class CardsNg1BootstrapperComponent { } angular.module(moduleName, []) - .controller('CardTestController', CardTestController) - .config(CardRoute); \ No newline at end of file + .component('tsCardsNg1', { + template: require('./cardsNg1.html'), + controller: 'CardTestController', + controllerAs: 'cards', + }) + .controller('CardTestController', CardTestController); diff --git a/bootstrapper/cards/cardRoot.ts b/bootstrapper/cards/cardRoot.ts new file mode 100644 index 00000000..862eabfe --- /dev/null +++ b/bootstrapper/cards/cardRoot.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsCardsRoot', + template: require('./cards.html'), +}) +export class CardsRootComponent { } diff --git a/bootstrapper/cards/cards.html b/bootstrapper/cards/cards.html index 558b21de..7ac771d0 100644 --- a/bootstrapper/cards/cards.html +++ b/bootstrapper/cards/cards.html @@ -1,5 +1,5 @@ -
\ No newline at end of file + diff --git a/bootstrapper/forms/forms.html b/bootstrapper/forms/forms.html index 58913cd8..7ac771d0 100644 --- a/bootstrapper/forms/forms.html +++ b/bootstrapper/forms/forms.html @@ -1,5 +1,5 @@ -
\ No newline at end of file + diff --git a/bootstrapper/forms/formsBootstrapper.ts b/bootstrapper/forms/formsBootstrapper.ts index b9061fd7..817f3748 100644 --- a/bootstrapper/forms/formsBootstrapper.ts +++ b/bootstrapper/forms/formsBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; import { services } from 'typescript-angular-utilities'; @@ -30,25 +31,16 @@ class FormTestController { } } -FormRoute.$inject = ['$stateProvider']; -function FormRoute($stateProvider) { - $stateProvider - .state('forms', { - url: '/forms', - template: require('./forms.html'), - }) - .state('forms.ng1', { - url: '/ng1', - template: require('./formsNg1.html'), - controller: 'FormTestController', - controllerAs: 'forms', - }) - .state('forms.ng2', { - url: '/ng2', - template: '', - }); -} +@Component({ + selector: 'tsFormsNg1', + template: '' +}) +export class FormsNg1BootstrapperComponent { } angular.module(moduleName, []) - .controller('FormTestController', FormTestController) - .config(FormRoute); + .component('tsFormsNg1', { + template: require('./formsNg1.html'), + controller: 'FormTestController', + controllerAs: 'forms', + }) + .controller('FormTestController', FormTestController); diff --git a/bootstrapper/forms/formsNg2.html b/bootstrapper/forms/formsNg2.html index c9de25ed..f1459008 100644 --- a/bootstrapper/forms/formsNg2.html +++ b/bootstrapper/forms/formsNg2.html @@ -4,7 +4,7 @@
Form with validation
- + Submit @@ -27,7 +27,7 @@
Form with names
Submit right
Autosave form
- + diff --git a/bootstrapper/forms/formsNg2Bootstrapper.ts b/bootstrapper/forms/formsNg2Bootstrapper.ts index f8d04b0a..8bcbf24e 100644 --- a/bootstrapper/forms/formsNg2Bootstrapper.ts +++ b/bootstrapper/forms/formsNg2Bootstrapper.ts @@ -1,4 +1,5 @@ import { Component, ViewChild } from '@angular/core'; +import { Observable, BehaviorSubject } from 'rxjs'; import { FormComponent } from '../../source/components/form/form'; import { AutosaveActionService } from '../../source/services/autosaveAction/autosaveAction.service'; @@ -12,6 +13,7 @@ export class FormsBootstrapper { rating: number; validator: any; brokenValidator: any; + rating$: BehaviorSubject; @ViewChild('testForm') testForm: FormComponent; @@ -20,16 +22,21 @@ export class FormsBootstrapper { constructor(autosaveAction: AutosaveActionService) { this.autosaveAction = autosaveAction; + this.rating$ = new BehaviorSubject(null); + this.validator = { - validate: () => this.rating >= 3, - errorMessage: 'You must give at least 3 stars', + validate: () => this.rating$.map(rating => rating >= 3 ? null : 'You must give at least 3 stars'), }; this.brokenValidator = { - validate: () => false, - errorMessage: null, + validate: () => Observable.of('error'), }; } + setRating(rating): void { + this.rating = rating; + this.rating$.next(rating); + } + waitCallback: { (data: any): Promise } = (data: any) => { return new Promise((resolve: Function, reject: Function): void => { setTimeout(() => { @@ -45,4 +52,4 @@ export class FormsBootstrapper { } return false; } -} \ No newline at end of file +} diff --git a/bootstrapper/forms/formsRoot.ts b/bootstrapper/forms/formsRoot.ts new file mode 100644 index 00000000..18d04070 --- /dev/null +++ b/bootstrapper/forms/formsRoot.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsFormsRoot', + template: require('./forms.html'), +}) +export class FormsRootComponent { } diff --git a/bootstrapper/inputs/inputBootstrapper.ts b/bootstrapper/inputs/inputBootstrapper.ts index f30644fb..90cff97f 100644 --- a/bootstrapper/inputs/inputBootstrapper.ts +++ b/bootstrapper/inputs/inputBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; import * as _ from 'lodash'; import * as moment from 'moment'; @@ -84,25 +85,16 @@ class InputTestController { } } -InputRoute.$inject = ['$stateProvider']; -function InputRoute($stateProvider) { - $stateProvider - .state('inputs', { - url: '/inputs', - template: require('./inputs.html'), - }) - .state('inputs.ng1', { - url: '/ng1', - template: require('./inputsNg1.html'), - controller: 'InputTestController', - controllerAs: 'input', - }) - .state('inputs.ng2', { - url: '/ng2', - template: '', - }); -} +@Component({ + selector: 'tsInputsNg1', + template: '' +}) +export class InputsNg1BootstrapperComponent { } angular.module(moduleName, []) - .controller('InputTestController', InputTestController) - .config(InputRoute); \ No newline at end of file + .component('tsInputsNg1', { + template: require('./inputsNg1.html'), + controller: 'InputTestController', + controllerAs: 'input', + }) + .controller('InputTestController', InputTestController); diff --git a/bootstrapper/inputs/inputRoot.ts b/bootstrapper/inputs/inputRoot.ts new file mode 100644 index 00000000..a201f439 --- /dev/null +++ b/bootstrapper/inputs/inputRoot.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsInputsRoot', + template: require('./inputs.html'), +}) +export class InputsRootComponent { } diff --git a/bootstrapper/inputs/inputs.html b/bootstrapper/inputs/inputs.html index f7b33119..7ac771d0 100644 --- a/bootstrapper/inputs/inputs.html +++ b/bootstrapper/inputs/inputs.html @@ -1,5 +1,5 @@ -
\ No newline at end of file + diff --git a/bootstrapper/inputs/inputsNg2.html b/bootstrapper/inputs/inputsNg2.html index 26a4e829..6f74f658 100644 --- a/bootstrapper/inputs/inputsNg2.html +++ b/bootstrapper/inputs/inputsNg2.html @@ -34,7 +34,7 @@

- +

diff --git a/bootstrapper/messageLog/messageLogBootstrapper.ts b/bootstrapper/messageLog/messageLogBootstrapper.ts index 2c5e6ffa..139af4e7 100644 --- a/bootstrapper/messageLog/messageLogBootstrapper.ts +++ b/bootstrapper/messageLog/messageLogBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; import * as _ from 'lodash'; import * as moment from 'moment'; @@ -79,17 +80,16 @@ class MessageLogTestController { } } -MessageLogRoute.$inject = ['$stateProvider']; -function MessageLogRoute($stateProvider) { - $stateProvider - .state('messageLog', { - url: '/messageLog', - template: require('./messageLogTest.html'), - controller: 'MessageLogTestController', - controllerAs: 'messageLog', - }); -} +@Component({ + selector: 'tsMessageLogNg1', + template: '' +}) +export class MessageLogNg1BootstrapperComponent { } angular.module(moduleName, []) - .controller('MessageLogTestController', MessageLogTestController) - .config(MessageLogRoute); \ No newline at end of file + .component('tsMessageLogNg1', { + template: require('./messageLogTest.html'), + controller: 'MessageLogTestController', + controllerAs: 'messageLog', + }) + .controller('MessageLogTestController', MessageLogTestController); diff --git a/bootstrapper/messageLog/messageLogTest.html b/bootstrapper/messageLog/messageLogTest.html index be0b0650..3ae1283c 100644 --- a/bootstrapper/messageLog/messageLogTest.html +++ b/bootstrapper/messageLog/messageLogTest.html @@ -1,4 +1,4 @@

Message log

- -
\ No newline at end of file + +
diff --git a/bootstrapper/misc/misc.html b/bootstrapper/misc/misc.html index fb545968..7ac771d0 100644 --- a/bootstrapper/misc/misc.html +++ b/bootstrapper/misc/misc.html @@ -1,5 +1,5 @@
-
\ No newline at end of file + diff --git a/bootstrapper/misc/miscBootstrapper.ts b/bootstrapper/misc/miscBootstrapper.ts index 34b0e25c..4d60bc0b 100644 --- a/bootstrapper/misc/miscBootstrapper.ts +++ b/bootstrapper/misc/miscBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; import * as moment from 'moment'; @@ -45,27 +46,27 @@ class MiscTestController { } } -MiscRoute.$inject = ['$stateProvider']; -function MiscRoute($stateProvider) { - $stateProvider - .state('misc', { - url: '/misc', - template: require('./misc.html'), - }) - .state('misc.ng1', { - url: '/ng1', - template: require('./miscNg1.html'), - controller: 'MiscTestController', - controllerAs: 'misc', - }) - .state('misc.ng2', { - url: '/ng2', - template: require('./miscNg2.html'), - controller: 'MiscTestController', - controllerAs: 'misc', - }); -} +@Component({ + selector: 'tsMiscNg1', + template: '' +}) +export class MiscNg1BootstrapperComponent { } + +@Component({ + selector: 'tsMiscNg2', + template: '' +}) +export class MiscNg2BootstrapperComponent {} angular.module(moduleName, []) - .controller('MiscTestController', MiscTestController) - .config(MiscRoute); + .component('tsMiscNg1', { + template: require('./miscNg1.html'), + controller: 'MiscTestController', + controllerAs: 'misc', + }) + .component('tsMiscNg2', { + template: require('./miscNg2.html'), + controller: 'MiscTestController', + controllerAs: 'misc', + }) + .controller('MiscTestController', MiscTestController); diff --git a/bootstrapper/misc/miscNg1.html b/bootstrapper/misc/miscNg1.html index c7c27a2b..1254524e 100644 --- a/bootstrapper/misc/miscNg1.html +++ b/bootstrapper/misc/miscNg1.html @@ -38,7 +38,7 @@

Misc

- +
@@ -86,4 +86,4 @@

Misc

-
\ No newline at end of file + diff --git a/bootstrapper/misc/miscRoot.ts b/bootstrapper/misc/miscRoot.ts new file mode 100644 index 00000000..a44688ae --- /dev/null +++ b/bootstrapper/misc/miscRoot.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsMiscRoot', + template: require('./misc.html'), +}) +export class MiscRootComponent { } diff --git a/bootstrapper/msi/msi.html b/bootstrapper/msi/msi.html deleted file mode 100644 index b7cb6aaa..00000000 --- a/bootstrapper/msi/msi.html +++ /dev/null @@ -1,5 +0,0 @@ - -
\ No newline at end of file diff --git a/bootstrapper/msi/msi.ng1.html b/bootstrapper/msi/msi.ng1.html deleted file mode 100644 index 034e8d2f..00000000 --- a/bootstrapper/msi/msi.ng1.html +++ /dev/null @@ -1,2 +0,0 @@ -

Multi Step Indicator Angular 1

- \ No newline at end of file diff --git a/bootstrapper/msi/msi.ng2.html b/bootstrapper/msi/msi.ng2.html index 37f23a26..903b4b04 100644 --- a/bootstrapper/msi/msi.ng2.html +++ b/bootstrapper/msi/msi.ng2.html @@ -1,6 +1,12 @@

Multi Step Indicator Angular 2

- \ No newline at end of file + [numbered]="numbered" + [checked]="checked" + [steps]="steps"> + +

rlStep

+ + diff --git a/bootstrapper/msi/msiBootstrapper.ng1.ts b/bootstrapper/msi/msiBootstrapper.ng1.ts deleted file mode 100644 index 94bd3927..00000000 --- a/bootstrapper/msi/msiBootstrapper.ng1.ts +++ /dev/null @@ -1,47 +0,0 @@ -import * as angular from 'angular'; - -import { IStep } from '../../source/components/multiStepIndicator/multiStepIndicator.ng1'; - -export const moduleName: string = 'MultiStepTestModule'; - -class MultiStepTestController { - steps: IStep[]; - - $onInit(): void { - this.steps = [ - { - title: 'Step 1', - subtitle: 'Do something', - onClick: (): void => console.log('Visited step 1'), - }, - { - title: 'Step 2', - subtitle: 'Do more work', - onClick: (): void => console.log('Visited step 2'), - }, - ]; - } -} - -MultiStepRoute.$inject = ['$stateProvider']; -function MultiStepRoute($stateProvider) { - $stateProvider - .state('msi', { - url: '/msi', - template: require('./msi.html'), - }) - .state('msi.ng1', { - url: '/ng1', - template: require('./msi.ng1.html'), - controller: 'MultiStepTestController', - controllerAs: 'vm', - }) - .state('msi.ng2', { - url: '/ng2', - template: '', - }); -} - -angular.module(moduleName, []) - .controller('MultiStepTestController', MultiStepTestController) - .config(MultiStepRoute); \ No newline at end of file diff --git a/bootstrapper/msi/msiBootstrapper.ng2.ts b/bootstrapper/msi/msiBootstrapper.ng2.ts index cdb98052..19f2db7c 100644 --- a/bootstrapper/msi/msiBootstrapper.ng2.ts +++ b/bootstrapper/msi/msiBootstrapper.ng2.ts @@ -1,4 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; +import { Observable } from 'rxjs'; import { IStep } from '../../source/components/multiStepIndicator/multiStepIndicator'; @@ -20,33 +21,22 @@ export class MsiBootstrapperComponent implements OnInit { this.steps = [ { title: 'Step 1', - stateName: 'ng2', - subtitle: 'Do something', - onClick: (): Promise<{}> => { - return new Promise( - function (resolve, reject) { - console.log('Processing step 1'); - setTimeout(() => { - console.log('Step 1 processed'); - resolve(); - }, 1000); - } - ); - }, + routerLink: ['/msi/ng1'], + subtitle: 'Angular 1', }, { title: 'Step 2', + routerLink: ['/msi/ng2'], + subtitle: 'Angular 2', + }, + { + title: 'Step 3', subtitle: 'Do more work', - onClick: (): Promise<{}> => { - return new Promise( - function (resolve, reject) { - console.log('Processing step 2'); - setTimeout(() => { - console.log('Step 2 processed'); - resolve(); - }, 1000); - } - ); + onClick: (): Observable => { + return Observable.of(null) + .do(() => console.log('Processing step 3')) + .delay(1000) + .do(() => console.log('Step 3 processed')); }, }, ]; diff --git a/bootstrapper/popup/popup.html b/bootstrapper/popup/popup.html index b346a0cc..7ac771d0 100644 --- a/bootstrapper/popup/popup.html +++ b/bootstrapper/popup/popup.html @@ -1,5 +1,5 @@ -
\ No newline at end of file + diff --git a/bootstrapper/popup/popupBootstrapper.ts b/bootstrapper/popup/popupBootstrapper.ts index 543770c3..e34ea448 100644 --- a/bootstrapper/popup/popupBootstrapper.ts +++ b/bootstrapper/popup/popupBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; import { serviceName as dialogService, bootstrapModalDialog } from '../../source/services/dialog/dialog.service.ng1'; @@ -37,25 +38,16 @@ class PopupTestController { } } -PopupRoute.$inject = ['$stateProvider']; -function PopupRoute($stateProvider) { - $stateProvider - .state('popup', { - url: '/popup', - template: require('./popup.html'), - }) - .state('popup.ng1', { - url: '/ng1', - template: require('./popupNg1.html'), - controller: 'PopupTestController', - controllerAs: 'popup', - }) - .state('popup.ng2', { - url: '/ng2', - template: '', - }); -} +@Component({ + selector: 'tsPopupNg1', + template: '' +}) +export class PopupNg1BootstrapperComponent { } angular.module(moduleName, []) - .controller('PopupTestController', PopupTestController) - .config(PopupRoute); + .component('tsPopupNg1', { + template: require('./popupNg1.html'), + controller: 'PopupTestController', + controllerAs: 'popup', + }) + .controller('PopupTestController', PopupTestController); diff --git a/bootstrapper/popup/popupNg2.html b/bootstrapper/popup/popupNg2.html index 30ffafe7..3287dfff 100644 --- a/bootstrapper/popup/popupNg2.html +++ b/bootstrapper/popup/popupNg2.html @@ -9,7 +9,7 @@

Popup content

Open Dialog 1 Open Dialog 2 Open prompt - +
Header
Content
Footer
diff --git a/bootstrapper/popup/popupRoot.ts b/bootstrapper/popup/popupRoot.ts new file mode 100644 index 00000000..955797d6 --- /dev/null +++ b/bootstrapper/popup/popupRoot.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsPopupRoot', + template: require('./popup.html'), +}) +export class PopupRootComponent { } diff --git a/bootstrapper/tabs/tabRoot.ts b/bootstrapper/tabs/tabRoot.ts new file mode 100644 index 00000000..34008076 --- /dev/null +++ b/bootstrapper/tabs/tabRoot.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsTabsRoot', + template: require('./tabs.html'), +}) +export class TabsRootComponent { } diff --git a/bootstrapper/tabs/tabs.html b/bootstrapper/tabs/tabs.html index a3b9bde5..03388f12 100644 --- a/bootstrapper/tabs/tabs.html +++ b/bootstrapper/tabs/tabs.html @@ -1,5 +1,5 @@ -
\ No newline at end of file + diff --git a/bootstrapper/tabs/tabsBootstrapper.ts b/bootstrapper/tabs/tabsBootstrapper.ts index 5938d2a3..17c8fdf6 100644 --- a/bootstrapper/tabs/tabsBootstrapper.ts +++ b/bootstrapper/tabs/tabsBootstrapper.ts @@ -1,3 +1,4 @@ +import { Component } from '@angular/core'; import * as angular from 'angular'; import { IStep } from '../../source/components/multiStepIndicator/multiStepIndicator'; @@ -8,25 +9,16 @@ class TabTestController { } -TabRoute.$inject = ['$stateProvider']; -function TabRoute($stateProvider) { - $stateProvider - .state('tabs', { - url: '/tabs', - template: require('./tabs.html'), - }) - .state('tabs.ng1', { - url: '/ng1', - template: require('./tabsNg1.html'), - controller: 'TabTestController', - controllerAs: 'tabs', - }) - .state('tabs.ng2', { - url: '/ng2', - template: '', - }); -} +@Component({ + selector: 'tsTabsNg1', + template: '' +}) +export class TabsNg1BootstrapperComponent { } angular.module(moduleName, []) - .controller('TabTestController', TabTestController) - .config(TabRoute); \ No newline at end of file + .component('tsTabsNg1', { + template: require('./tabsNg1.html'), + controller: 'TabTestController', + controllerAs: 'tabs', + }) + .controller('TabTestController', TabTestController); diff --git a/bootstrapper/tabs/tabsNg1.html b/bootstrapper/tabs/tabsNg1.html index 05f2485e..883b2328 100644 --- a/bootstrapper/tabs/tabsNg1.html +++ b/bootstrapper/tabs/tabsNg1.html @@ -12,5 +12,3 @@

Tabs Ng 1

Footer 2 - - \ No newline at end of file diff --git a/bootstrapper/text/text.ts b/bootstrapper/text/text.ts index 6fb88342..f14f8b29 100644 --- a/bootstrapper/text/text.ts +++ b/bootstrapper/text/text.ts @@ -2,12 +2,6 @@ import * as angular from 'angular'; export const moduleName: string = 'TextModule'; -const textComponent: angular.IComponentOptions = { - transclude: true, - template: '{{$ctrl.text}}', - controller: TextController, -}; - class TextController { text: string; @@ -21,5 +15,11 @@ class TextController { } } +const textComponent: angular.IComponentOptions = { + transclude: true, + template: '{{$ctrl.text}}', + controller: TextController, +}; + angular.module(moduleName, []) - .component('tsText', textComponent); \ No newline at end of file + .component('tsText', textComponent); diff --git a/bootstrapper/welcome.component.ts b/bootstrapper/welcome.component.ts new file mode 100644 index 00000000..44f72250 --- /dev/null +++ b/bootstrapper/welcome.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'tsWelcome', + template: '

Welcome to typescript-angular-components

', +}) +export class WelcomeComponent { } diff --git a/index.html b/index.html index 61242638..da94b0e1 100644 --- a/index.html +++ b/index.html @@ -6,17 +6,21 @@
+ + +
- +
+ diff --git a/package.json b/package.json index 8d136785..0537cb4f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "typescript-angular-components", - "version": "3.2.2", + "version": "3.6.0", "description": "Reusable responsive angular components", "author": "Renovo Development Team", "keywords": [ @@ -42,7 +42,7 @@ "build-bundle": "npm run build && npm run bundle", "build-bundle.watch": "concurrently --kill-others \"npm run build.watch\" \"npm run bundle.watch\"", - "serve": "http-server -c-1 -o", + "serve": "lite-server", "start": "concurrently --kill-others \"npm run bundle.watch\" \"npm run serve\"", "bundle-deps": "gulp bundle-bootstrapper-vendor && gulp bundle-bootstrapper-renovo && gulp bundle-tests-vendor && gulp bundle-tests-renovo" }, @@ -54,7 +54,6 @@ "gulp": "~3.9.1", "gulp-clean-css": "^2.0.7", "gulp-concat": "^2.6.0", - "http-server": "^0.9.0", "jasmine": "^2.5.2", "jasmine-core": "^2.5.2", "karma": "~0.13.21", @@ -65,26 +64,28 @@ "karma-jasmine": "~1.0.2", "karma-sinon": "~1.0.4", "karma-teamcity-reporter": "~0.2.1", + "lite-server": "^2.2.2", "reflect-metadata": "0.1.2", "run-sequence": "^1.1.5", "sinon": "~1.17.3", "system-css": "^0.1.0", "system-text": "^0.1.0", "systemjs-builder": "^0.15.16", + "traceur": "0.0.111", "typescript": "~2.0.3" }, "dependencies": { - "@angular/common": "~2.0.0", - "@angular/compiler": "~2.0.0", - "@angular/core": "~2.0.1", - "@angular/forms": "~2.0.0", - "@angular/http": "~2.0.0", - "@angular/platform-browser": "~2.0.0", - "@angular/platform-browser-dynamic": "~2.0.0", - "@angular/upgrade": "~2.0.0", + "@angular/common": "~2.1.0", + "@angular/compiler": "~2.1.0", + "@angular/core": "~2.1.0", + "@angular/forms": "~2.1.0", + "@angular/http": "~2.1.0", + "@angular/platform-browser": "~2.1.0", + "@angular/platform-browser-dynamic": "~2.1.0", + "@angular/router": "~3.1.0", + "@angular/upgrade": "~2.1.0", "@types/angular": "1.5.16", "@types/angular-ui-bootstrap": "^0.13.35", - "@types/angular-ui-router": "^1.1.34", "@types/bootstrap": "^3.3.32", "@types/bootstrap-touchspin": "0.0.29", "@types/chai": "^3.4.33", @@ -99,7 +100,6 @@ "angular-mocks": "~1.5.0", "angular-sanitize": "~1.5.0", "angular-ui-bootstrap": "~0.14.3", - "angular-ui-router": "1.0.0-alpha.1", "angular2-uuid": "^1.0.7", "bootstrap": "~3.3.6", "core-js": "^2.4.1", @@ -108,12 +108,12 @@ "moment": "~2.14.1", "moment-timezone": "^0.5.3", "ng-wig": "~2.3.4", - "rl-async-testing": "~1.3.2", - "rl-http": "~1.1.2", + "rl-async-testing": "~1.4.0", + "rl-http": "~1.2.0", "rxjs": "5.0.0-beta.12", "systemjs": "^0.19.28", "typescript": "^2.0.3", - "typescript-angular-utilities": "~3.7.0", + "typescript-angular-utilities": "~3.9.0", "ui-select": "~0.14.7", "zone.js": "~0.6.25" }, diff --git a/source/animations/index.ts b/source/animations/index.ts new file mode 100644 index 00000000..664330d4 --- /dev/null +++ b/source/animations/index.ts @@ -0,0 +1,5 @@ +import * as slide from './slide/slide.animate'; + +export { + slide, +} \ No newline at end of file diff --git a/source/animations/slide/slide.animate.ts b/source/animations/slide/slide.animate.ts new file mode 100644 index 00000000..80aa90d5 --- /dev/null +++ b/source/animations/slide/slide.animate.ts @@ -0,0 +1,17 @@ +import { AnimationEntryMetadata, trigger, state, style, transition, animate } from '@angular/core'; + +export const show: string = 'show'; +export const hide: string = 'hide'; + +export const animation = trigger('slide', [ + state(hide, style({ + zIndex: 1, + opacity: 0, + transform: 'translateY(100%)', + })), + state(show, style({ + opacity: 1, + transform: 'translateY(0)', + })), + transition(`${hide} <=> ${show}`, animate('250ms ease')), +]); \ No newline at end of file diff --git a/source/behaviors/autosave/autosave.tests.ts b/source/behaviors/autosave/autosave.tests.ts index 0564f2fa..e485f1b6 100644 --- a/source/behaviors/autosave/autosave.tests.ts +++ b/source/behaviors/autosave/autosave.tests.ts @@ -6,7 +6,8 @@ import { services } from 'typescript-angular-utilities'; import { AutosaveDirective, DEFAULT_AUTOSAVE_DEBOUNCE } from './autosave'; interface IFormMock { - form: { statusChanges: Subject }; + dirty: boolean; + form: { statusChanges: Subject }; validate: Sinon.SinonSpy; submitAndWait: Sinon.SinonSpy; saveForm: Sinon.SinonSpy; @@ -23,7 +24,10 @@ describe('AutosaveDirective', () => { beforeEach(() => { form = { - form: { statusChanges: new Subject() }, + dirty: true, + form: { + statusChanges: new Subject(), + }, validate: sinon.spy(() => true), submitAndWait: sinon.spy(), saveForm: sinon.spy(), @@ -89,6 +93,19 @@ describe('AutosaveDirective', () => { sinon.assert.notCalled(autosaveSpy); })); + it('should not trigger an autosave if the form is pristine', rlFakeAsync(() => { + const autosaveSpy = sinon.spy(); + autosave.autosave = autosaveSpy; + form.dirty = false; + + autosave.setDebounce(); + + rlTick(DEFAULT_AUTOSAVE_DEBOUNCE); + flushMicrotasks(); + + sinon.assert.notCalled(autosaveSpy); + })); + it('should still trigger an autosave if the form is invalid but saveWhenInvalid is enabled', rlFakeAsync(() => { const autosaveSpy = sinon.spy(); autosave.autosave = autosaveSpy; diff --git a/source/behaviors/autosave/autosave.ts b/source/behaviors/autosave/autosave.ts index 41a7885b..3e56cb21 100644 --- a/source/behaviors/autosave/autosave.ts +++ b/source/behaviors/autosave/autosave.ts @@ -34,7 +34,7 @@ export class AutosaveDirective implements AfterViewInit { } setDebounce = (): void => { - if (!this.timer && (this.saveWhenInvalid || this.form.validate())) { + if (!this.timer && this.form.dirty && (this.saveWhenInvalid || this.form.validate())) { this.timer = this.timeoutService.setTimeout(this.autosave, DEFAULT_AUTOSAVE_DEBOUNCE) .catch(() => null); } @@ -50,7 +50,9 @@ export class AutosaveDirective implements AfterViewInit { autosave = (): void => { const waitOn = this.submitAndWait(); - this.autosaveAction.trigger(waitOn); + if (waitOn) { + this.autosaveAction.trigger(waitOn); + } this.timer = null; } diff --git a/source/components/buttons/buttonRoute/buttonRoute.html b/source/components/buttons/buttonRoute/buttonRoute.html new file mode 100644 index 00000000..8cf062ad --- /dev/null +++ b/source/components/buttons/buttonRoute/buttonRoute.html @@ -0,0 +1,7 @@ + + + diff --git a/source/components/buttons/buttonRoute/buttonRoute.tests.ts b/source/components/buttons/buttonRoute/buttonRoute.tests.ts new file mode 100644 index 00000000..bcc4aaee --- /dev/null +++ b/source/components/buttons/buttonRoute/buttonRoute.tests.ts @@ -0,0 +1,18 @@ +import { ButtonRouteComponent } from './buttonRoute'; + +describe('ButtonRouteComponent', (): void => { + let buttonRoute: ButtonRouteComponent; + + beforeEach((): void => { + buttonRoute = new ButtonRouteComponent(); + }); + + it('should set the target to blank if newTab is set', (): void => { + buttonRoute.newTab = true; + expect(buttonRoute.target).to.equal('_blank'); + }); + + it('should set the target to self by default', (): void => { + expect(buttonRoute.target).to.equal('_self'); + }); +}); diff --git a/source/components/buttons/buttonRoute/buttonRoute.ts b/source/components/buttons/buttonRoute/buttonRoute.ts new file mode 100644 index 00000000..43cf3a56 --- /dev/null +++ b/source/components/buttons/buttonRoute/buttonRoute.ts @@ -0,0 +1,18 @@ +import { Component, Input } from '@angular/core'; + +import { BaseButtonComponent, baseInputs } from '../baseButton'; + +@Component({ + selector: 'rlButtonRoute', + template: require('./buttonRoute.html'), + inputs: baseInputs, +}) +export class ButtonRouteComponent extends BaseButtonComponent { + @Input() link: string; + @Input() activeClass: string = 'active'; + @Input() newTab: boolean; + + get target(): string { + return this.newTab ? '_blank' : '_self'; + } +} diff --git a/source/components/buttons/index.ts b/source/components/buttons/index.ts index 9e528e84..5cf13e2e 100644 --- a/source/components/buttons/index.ts +++ b/source/components/buttons/index.ts @@ -2,6 +2,7 @@ import { ButtonComponent } from './button/button'; import { ButtonAsyncComponent } from './buttonAsync/buttonAsync'; import { ButtonLinkComponent } from './buttonLink/buttonLink'; import { ButtonLongClickComponent } from './buttonLongClick/buttonLongClick'; +import { ButtonRouteComponent } from './buttonRoute/buttonRoute'; import { ButtonSubmitComponent } from './buttonSubmit/buttonSubmit'; import { ButtonToggleComponent } from './buttonToggle/buttonToggle'; @@ -10,6 +11,7 @@ export const BUTTON_DIRECTIVES: any[] = [ ButtonAsyncComponent, ButtonLinkComponent, ButtonLongClickComponent, + ButtonRouteComponent, ButtonSubmitComponent, ButtonToggleComponent, ]; @@ -18,5 +20,6 @@ export * from './button/button'; export * from './buttonAsync/buttonAsync'; export * from './buttonLink/buttonLink'; export * from './buttonLongClick/buttonLongClick'; +export * from './buttonRoute/buttonRoute'; export * from './buttonSubmit/buttonSubmit'; -export * from './buttonToggle/buttonToggle'; \ No newline at end of file +export * from './buttonToggle/buttonToggle'; diff --git a/source/components/cardContainer/cardContainer.ng1.html b/source/components/cardContainer/cardContainer.ng1.html index 2f4faedc..28f3af98 100644 --- a/source/components/cardContainer/cardContainer.ng1.html +++ b/source/components/cardContainer/cardContainer.ng1.html @@ -39,7 +39,7 @@ -
+
Please refine your search results
diff --git a/source/components/cardContainer/cardContainer.ng1.tests.ts b/source/components/cardContainer/cardContainer.ng1.tests.ts index d0e0a945..cb997208 100644 --- a/source/components/cardContainer/cardContainer.ng1.tests.ts +++ b/source/components/cardContainer/cardContainer.ng1.tests.ts @@ -592,27 +592,6 @@ describe('CardContainerController', () => { }); }); - describe('hasItems', (): void => { - it('should return true if the data set is not empty', (): void => { - let dataSource: IDataSourceMock; - dataSource = buildMockedDataSource(); - dataSource.rawDataSet = [ - { id: 0 }, - { id: 1 }, - ]; - dataSource.dataSet = dataSource.rawDataSet; - buildController(); - - cardContainer.dataSource.dataSet = []; - - expect(cardContainer.hasItems).to.be.false; - - cardContainer.dataSource.dataSet = [1]; - - expect(cardContainer.hasItems).to.be.true; - }); - }); - function buildController(): void { if (cardContainer.dataSource == null && builder._dataSource == null) { mockedDataSource = buildMockedDataSource(); diff --git a/source/components/cardContainer/cardContainer.ng1.ts b/source/components/cardContainer/cardContainer.ng1.ts index b2c01c5e..971e9ac7 100644 --- a/source/components/cardContainer/cardContainer.ng1.ts +++ b/source/components/cardContainer/cardContainer.ng1.ts @@ -240,10 +240,6 @@ export class CardContainerController { this.selectionChangedEvent(); } - get hasItems(): boolean { - return this.dataSource.dataSet && !!this.dataSource.dataSet.length; - } - private syncFilters(): void { if (!this.object.isNullOrEmpty(this.filters)) { this.dataSource.filters = this.filters; diff --git a/source/components/cardContainer/cardContainer.ts b/source/components/cardContainer/cardContainer.ts index 9335225a..743d7d1f 100644 --- a/source/components/cardContainer/cardContainer.ts +++ b/source/components/cardContainer/cardContainer.ts @@ -84,7 +84,7 @@ export class CardContainerComponent implements OnInit { this.arrayUtility = array; this.injectedPager = pager; this.sortManager = sortManager; - this.save = () => Promise.resolve(); + this.save = () => null; } ngOnInit(): void { diff --git a/source/components/cardContainer/dataSources/simpleDataSource/simpleDataSource.service.ts b/source/components/cardContainer/dataSources/simpleDataSource/simpleDataSource.service.ts index 3dca09f8..bc712bba 100644 --- a/source/components/cardContainer/dataSources/simpleDataSource/simpleDataSource.service.ts +++ b/source/components/cardContainer/dataSources/simpleDataSource/simpleDataSource.service.ts @@ -14,6 +14,7 @@ export class SimpleDataSource extends DataSourceBase { super(dataSourceProcessor, array); this.countFilterGroups = false; this.rawDataSet = data; + this.isEmpty = !(data && data.length); this.processData(); } } diff --git a/source/components/components.module.ts b/source/components/components.module.ts index 8aff0d8e..568c364e 100644 --- a/source/components/components.module.ts +++ b/source/components/components.module.ts @@ -18,7 +18,6 @@ import * as inputNg1 from './inputs/input.ng1'; import * as lazyLoadNg1 from './lazyLoad/lazyLoad'; import * as longClickButtonNg1 from './buttons/buttonLongClick/buttonLongClick.ng1'; import * as messageLogNg1 from './messageLog/messageLog.module'; -import * as multiStepIndicatorNg1 from './multiStepIndicator/multiStepIndicator.ng1'; import * as radioNg1 from './inputs/radio/radio.module'; import * as ratingBarNg1 from './ratingBar/ratingBar.ng1'; import * as richTextEditorNg1 from './richTextEditor/richTextEditor'; @@ -43,6 +42,7 @@ import * as commaList from './commaList/commaList'; import * as dialog from './dialog/index'; import * as inputs from './inputs/index'; import * as form from './form/index'; +import * as multiStepIndicator from './multiStepIndicator/multiStepIndicator'; import * as ratingBar from './ratingBar/ratingBar'; import * as simpleCardList from './simpleCardList/index'; import * as stringWithWatermark from './stringWithWatermark/stringWithWatermark'; @@ -71,7 +71,6 @@ export { lazyLoadNg1, longClickButtonNg1, messageLogNg1, - multiStepIndicatorNg1, radioNg1, ratingBarNg1, richTextEditorNg1, @@ -96,6 +95,7 @@ export { dialog, inputs, form, + multiStepIndicator, ratingBar, simpleCardList, stringWithWatermark, @@ -122,7 +122,6 @@ angular.module(moduleName, [ lazyLoadNg1.moduleName, longClickButtonNg1.moduleName, messageLogNg1.moduleName, - multiStepIndicatorNg1.moduleName, radioNg1.moduleName, ratingBarNg1.moduleName, richTextEditorNg1.moduleName, diff --git a/source/components/dialog/dialog.tests.ts b/source/components/dialog/dialog.tests.ts index d6e19fd1..d0995b24 100644 --- a/source/components/dialog/dialog.tests.ts +++ b/source/components/dialog/dialog.tests.ts @@ -20,6 +20,7 @@ describe('DialogComponent', (): void => { dialog.content = {}; dialog.footer = {}; dialog.autosave = true; + dialog.size = 'sm'; const openSpy = sinon.spy(); dialogRoot.openDialog.subscribe(openSpy); @@ -32,6 +33,7 @@ describe('DialogComponent', (): void => { expect(arg.content).to.equal(dialog.content); expect(arg.footer).to.equal(dialog.footer); expect(arg.autosave).to.equal(dialog.autosave); + expect(arg.size).to.equal(dialog.size); expect(isFunction(arg.submitAndClose)); }); @@ -124,4 +126,4 @@ describe('DialogComponent', (): void => { expect(dialog.wrapOnClosing()).to.be.true; }); }); -}); \ No newline at end of file +}); diff --git a/source/components/dialog/dialog.ts b/source/components/dialog/dialog.ts index f84809ea..0111e527 100644 --- a/source/components/dialog/dialog.ts +++ b/source/components/dialog/dialog.ts @@ -23,6 +23,7 @@ import { FormService } from '../../services/form/form.service'; export class DialogComponent extends FormComponent { @Input() onClosing: IDialogClosingHandler; @Input() autosave: boolean; + @Input() size: string; @ContentChild(DialogHeaderTemplate) header: DialogHeaderTemplate; @ContentChild(DialogContentTemplate) content: DialogContentTemplate; @@ -46,6 +47,7 @@ export class DialogComponent extends FormComponent { footer: this.footer, autosave: this.autosave, submitAndClose: () => this.submitAndClose(), + size: this.size, }); } diff --git a/source/components/dialog/dialogOutlet.html b/source/components/dialog/dialogOutlet.html index 127153d9..8bf2620d 100644 --- a/source/components/dialog/dialogOutlet.html +++ b/source/components/dialog/dialogOutlet.html @@ -1,5 +1,5 @@ diff --git a/source/components/dialog/dialogOutlet.tests.ts b/source/components/dialog/dialogOutlet.tests.ts index d40ee25c..e97a7a32 100644 --- a/source/components/dialog/dialogOutlet.tests.ts +++ b/source/components/dialog/dialogOutlet.tests.ts @@ -52,6 +52,26 @@ describe('DialogOutletComponent', (): void => { sinon.assert.calledOnce(closeSpy); }); + describe('dialogSize$', () => { + it('should return the current dialog size prefixed with \'model-\'', () => { + let size: string; + dialogOutlet.dialogSize$.subscribe(_size => size = _size); + + dialogRoot.openDialog.next({ size: 'sm' }); + + expect(size).to.equal('modal-sm'); + }); + + it('should default to an empty string', () => { + let size: string; + dialogOutlet.dialogSize$.subscribe(_size => size = _size); + + dialogRoot.openDialog.next({}); + + expect(size).to.be.empty; + }); + }); + describe('onClosing', (): void => { beforeEach((): void => { dialogOutlet.ngAfterViewInit(); @@ -100,4 +120,4 @@ describe('DialogOutletComponent', (): void => { sinon.assert.notCalled(event.preventDefault); }); }); -}); \ No newline at end of file +}); diff --git a/source/components/dialog/dialogOutlet.ts b/source/components/dialog/dialogOutlet.ts index 7a09f851..dbb7ddb3 100644 --- a/source/components/dialog/dialogOutlet.ts +++ b/source/components/dialog/dialogOutlet.ts @@ -1,5 +1,6 @@ import 'bootstrap'; import { Component, AfterViewInit, Inject } from '@angular/core'; +import { Observable } from 'rxjs'; import { DialogRootService } from './dialogRoot.service'; import { JQueryProvider } from '../../services/jquery/jquery.provider'; @@ -11,6 +12,7 @@ import { JQueryProvider } from '../../services/jquery/jquery.provider'; export class DialogOutletComponent implements AfterViewInit { dialogRoot: DialogRootService; jquery: JQueryStatic; + dialogSize$: Observable; constructor(dialogRoot: DialogRootService , jquery: JQueryProvider) { @@ -22,6 +24,9 @@ export class DialogOutletComponent implements AfterViewInit { dialogRoot.closeDialog.subscribe((): void => { this.jquery('.rlModal').modal('hide'); }); + this.dialogSize$ = dialogRoot.openDialog.map(dialog => { + return dialog.size ? `modal-${dialog.size}` : ''; + }); } dismiss(): void { diff --git a/source/components/dialog/dialogRoot.service.ts b/source/components/dialog/dialogRoot.service.ts index 8cfd76ef..0666959b 100644 --- a/source/components/dialog/dialogRoot.service.ts +++ b/source/components/dialog/dialogRoot.service.ts @@ -9,6 +9,7 @@ export interface IDialogContent { footer?: DialogFooterTemplate; autosave?: boolean; submitAndClose?: { (): void }; + size?: string; } export interface IDialogClosingHandler { @@ -33,4 +34,4 @@ export class DialogRootService { return true; } } -} \ No newline at end of file +} diff --git a/source/components/form/form.ts b/source/components/form/form.ts index 8b563a0a..ae8cc660 100644 --- a/source/components/form/form.ts +++ b/source/components/form/form.ts @@ -49,7 +49,7 @@ export class FormComponent { this.form = new FormGroup({}); this.form.rlNestedFormGroups = []; if (!this.save) { - this.save = () => Promise.resolve(); + this.save = () => null; } if (parentForm) { diff --git a/source/components/inputs/absoluteTime/absoluteTime.html b/source/components/inputs/absoluteTime/absoluteTime.html index bb108552..db1ec314 100644 --- a/source/components/inputs/absoluteTime/absoluteTime.html +++ b/source/components/inputs/absoluteTime/absoluteTime.html @@ -1,10 +1,13 @@
- + @@ -42,7 +45,7 @@
-
- {{componentValidator.error}} +
+ {{componentValidator.error$ | async}}
-
\ No newline at end of file + diff --git a/source/components/inputs/absoluteTime/absoluteTime.tests.ts b/source/components/inputs/absoluteTime/absoluteTime.tests.ts index eabf3951..d2401d39 100644 --- a/source/components/inputs/absoluteTime/absoluteTime.tests.ts +++ b/source/components/inputs/absoluteTime/absoluteTime.tests.ts @@ -1,3 +1,4 @@ +import { Observable } from 'rxjs'; import { services } from 'typescript-angular-utilities'; import __time = services.time; import __object = services.object; @@ -14,8 +15,8 @@ describe('AbsoluteTimeComponent', () => { beforeEach(() => { const validator: any = { - validate: sinon.spy(), - setValidators: sinon.spy(), + validate: sinon.spy(() => Observable.empty()), + initValidator: sinon.spy(), }; setValue = sinon.spy(); diff --git a/source/components/inputs/absoluteTime/absoluteTime.ts b/source/components/inputs/absoluteTime/absoluteTime.ts index 1b0dc8fc..5ee1e8c4 100644 --- a/source/components/inputs/absoluteTime/absoluteTime.ts +++ b/source/components/inputs/absoluteTime/absoluteTime.ts @@ -12,12 +12,15 @@ import { ValidatedInputComponent, validationInputs, baseOutputs } from '../valid import { ComponentValidator } from '../../../services/componentValidator/componentValidator.service'; import { FormComponent } from '../../form/form'; +import { baseAnimations } from '../input'; + @Component({ selector: 'rlAbsoluteTime', template: require('./absoluteTime.html'), inputs: validationInputs, outputs: baseOutputs, providers: [ComponentValidator], + animations: baseAnimations, }) export class AbsoluteTimeComponent extends ValidatedInputComponent implements OnInit { @Input() minuteInterval: number = 15; diff --git a/source/components/inputs/dateTime/dateTime.html b/source/components/inputs/dateTime/dateTime.html index 2d2e501c..49943f7b 100644 --- a/source/components/inputs/dateTime/dateTime.html +++ b/source/components/inputs/dateTime/dateTime.html @@ -1,12 +1,15 @@
- + @@ -21,7 +24,7 @@ -
- {{componentValidator.error}} +
+ {{componentValidator.error$ | async}}
-
\ No newline at end of file +
diff --git a/source/components/inputs/dateTime/dateTime.ts b/source/components/inputs/dateTime/dateTime.ts index 3e0a1a8b..b035625d 100644 --- a/source/components/inputs/dateTime/dateTime.ts +++ b/source/components/inputs/dateTime/dateTime.ts @@ -1,4 +1,4 @@ -import { Component, Optional, Input, Output, EventEmitter, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; +import { Component, Optional, Input, Output, EventEmitter, AfterViewInit, OnInit, ElementRef, ViewChild } from '@angular/core'; import { isUndefined } from 'lodash'; import * as moment from 'moment'; import * as $ from 'jquery'; @@ -16,14 +16,17 @@ import { ValidatedInputComponent, validationInputs, baseOutputs } from '../valid import { ComponentValidator } from '../../../services/componentValidator/componentValidator.service'; import { FormComponent } from '../../form/form'; +import { baseAnimations } from '../input'; + @Component({ selector: 'rlDateTime', template: require('./dateTime.html'), inputs: validationInputs, outputs: baseOutputs, providers: [ComponentValidator], + animations: baseAnimations, }) -export class DateTimeComponent extends ValidatedInputComponent implements AfterViewInit { +export class DateTimeComponent extends ValidatedInputComponent implements OnInit, AfterViewInit { @Input() useDate: boolean; @Input() useTime: boolean; @Input() min: string | Date | moment.Moment; @@ -58,8 +61,8 @@ export class DateTimeComponent extends ValidatedInputComponent im this.timezone = this.timezoneService.currentTimezone; } - ngAfterViewInit(): void { - super.ngAfterViewInit(); + ngOnInit(): void { + super.ngOnInit(); this.useDate = isUndefined(this.useDate) ? true : this.useDate; this.useTime = isUndefined(this.useTime) ? true : this.useTime; @@ -76,6 +79,10 @@ export class DateTimeComponent extends ValidatedInputComponent im this.control.valueChanges.subscribe(value => { this.valueAsString = this.formatDate(value); }); + } + + ngAfterViewInit(): void { + super.ngAfterViewInit(); $(this.datepicker.nativeElement).datetimepicker({ stepping: this.minuteStepping || 1, diff --git a/source/components/inputs/input.tests.ts b/source/components/inputs/input.tests.ts index f4cf8b08..7247f08a 100644 --- a/source/components/inputs/input.tests.ts +++ b/source/components/inputs/input.tests.ts @@ -50,6 +50,20 @@ describe('InputComponent', (): void => { expect(input.name).to.equal('name'); }); + it('should show the label if the form control already has a value set', (): void => { + input.value = 12345; + input.ngOnInit(); + + expect(input.labelState).to.equal('show'); + }); + + it('should hide the label if the form control has no value already set', (): void => { + input.value = null; + input.ngOnInit(); + + expect(input.labelState).to.equal('hide'); + }); + it('should add the control to the form using the name if a form is present', (): void => { const control: any = { valueChanges: new Subject() }; input.control = control; @@ -100,4 +114,38 @@ describe('InputComponent', (): void => { input.setValue(4); expect(input.value).to.be.undefined; }); + + it('should show the label', (): void => { + input.showLabel(); + + expect(input.labelState).to.equal('show'); + }); + + it('should hide the label if the form control is empty', (): void => { + input.value = null; + input.hideLabelIfEmpty(); + + expect(input.labelState).to.equal('hide'); + }); + + it('should not hide the label if the form control has a value', (): void => { + input.value = 12345; + input.hideLabelIfEmpty(); + + expect(input.labelState).to.equal('show'); + }); + + it('should show the placeholder if the label is hidden', (): void => { + input.labelState = 'hide'; + input.isLabelShowing(); + + expect(input.hidePlaceholder).to.be.false; + }); + + it('should hide the placeholder if the label is shown', (): void => { + input.labelState = 'show'; + input.isLabelShowing(); + + expect(input.hidePlaceholder).to.be.true; + }); }); diff --git a/source/components/inputs/input.ts b/source/components/inputs/input.ts index a5cc4a18..3d8174ae 100644 --- a/source/components/inputs/input.ts +++ b/source/components/inputs/input.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, OnInit, EventEmitter } from '@angular/core'; +import { Component, AfterViewInit, OnInit, EventEmitter, AnimationEntryMetadata } from '@angular/core'; import { FormControl } from '@angular/forms'; import { services } from 'typescript-angular-utilities'; @@ -6,9 +6,11 @@ import __object = services.object; import __guid = services.guid; import { FormComponent } from '../form/form'; +import { slide } from '../../animations/index'; export const baseInputs: string[] = ['name', 'label', 'value', 'disabled']; export const baseOutputs: string[] = ['change', 'valueChange']; +export const baseAnimations = [slide.animation]; export class InputComponent implements AfterViewInit, OnInit { name: string; @@ -16,6 +18,8 @@ export class InputComponent implements AfterViewInit, OnInit { disabled: boolean; warning: boolean; value: T; + labelState: string = slide.hide; + hidePlaceholder: boolean = false; change: EventEmitter = new EventEmitter(); valueChange: EventEmitter = this.change; @@ -37,6 +41,10 @@ export class InputComponent implements AfterViewInit, OnInit { if (this.object.isNullOrEmpty(this.name)) { this.name = this.inputType + '-' + this.guid.random(); } + + if (this.value) { + this.showLabel(); + } } ngAfterViewInit(): void { @@ -63,4 +71,22 @@ export class InputComponent implements AfterViewInit, OnInit { this.change.emit(value); } } + + isLabelShowing(): boolean { + return this.labelState == slide.show + ? this.hidePlaceholder = true + : this.hidePlaceholder = false; + } + + showLabel(): void { + this.labelState = slide.show; + this.isLabelShowing(); + } + + hideLabelIfEmpty(): void { + this.value + ? this.showLabel() + : this.labelState = slide.hide; + this.isLabelShowing(); + } } diff --git a/source/components/inputs/select/select.html b/source/components/inputs/select/select.html index ee8a1122..202a785e 100644 --- a/source/components/inputs/select/select.html +++ b/source/components/inputs/select/select.html @@ -1,24 +1,28 @@
- +
- {{label}} + {{label}} {{getDisplayName(value)}}
{{nullOption}} - -
- {{componentValidator.error}} + +
+ {{componentValidator.error$ | async}}
-
\ No newline at end of file +
diff --git a/source/components/inputs/select/select.ng1.html b/source/components/inputs/select/select.ng1.html index c3827595..d39f10f3 100644 --- a/source/components/inputs/select/select.ng1.html +++ b/source/components/inputs/select/select.ng1.html @@ -1,18 +1,20 @@ -
+
+ ng-class="{ 'disabled': select.ngDisabled, 'rl-select-open': select.showOptions }" + ng-mousedown="select.toggle()" + ng-blur="select.close()" + tabindex="0"> {{::select.label}} {{select.getDisplayName(select.selection)}}
    -
  • {{::select.nullOption}}
  • +
  • {{::select.nullOption}}
  • + ng-mousedown="select.selectOption($item)">
diff --git a/source/components/inputs/select/select.ng1.tests.ts b/source/components/inputs/select/select.ng1.tests.ts index 4c663012..7e2109bd 100644 --- a/source/components/inputs/select/select.ng1.tests.ts +++ b/source/components/inputs/select/select.ng1.tests.ts @@ -117,14 +117,9 @@ describe('SelectController', () => { it('should close the options', (): void => { dropdown.showOptions = true; dropdown.close(); - expect(dropdown.showOptions).to.be.false; - }); - it('should do nothing if the options are already closed', (): void => { - dropdown.showOptions = false; - dropdown.close(); expect(dropdown.showOptions).to.be.false; - }); + }) it('should set the value and close the options', (): void => { dropdown.showOptions = true; diff --git a/source/components/inputs/select/select.ng1.ts b/source/components/inputs/select/select.ng1.ts index ca108627..cd6b1ad3 100644 --- a/source/components/inputs/select/select.ng1.ts +++ b/source/components/inputs/select/select.ng1.ts @@ -96,10 +96,8 @@ export class SelectController extends InputController { this.showOptions = !this.showOptions; } - close: { (): void } = () => { - if (this.showOptions) { - this.showOptions = false; - } + close(): void { + this.showOptions = false; } selectOption(value: any): void { diff --git a/source/components/inputs/select/select.tests.ts b/source/components/inputs/select/select.tests.ts index 49fce75e..be53f3b1 100644 --- a/source/components/inputs/select/select.tests.ts +++ b/source/components/inputs/select/select.tests.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject } from 'rxjs'; +import { Observable } from 'rxjs'; import { SelectComponent } from './select'; @@ -24,8 +24,7 @@ describe('SelectComponent', () => { beforeEach(() => { transformService = { getValue: sinon.spy() }; const validator: any = { - validate: sinon.spy(), - afterInit: sinon.spy(), + validate: sinon.spy(() => Observable.empty()), }; dropdown = new SelectComponent(transformService, null, validator, null, null, null); @@ -45,36 +44,6 @@ describe('SelectComponent', () => { ]; }); - describe('after init', (): void => { - afterEach((): void => { - sinon.assert.calledOnce(busy.trigger); - sinon.assert.calledWith(busy.trigger, dropdown.wrappedOptions); - }); - - it('should wrap the array in an observable', (): void => { - const unwrapper: Sinon.SinonSpy = sinon.spy(); - dropdown.options = options; - - dropdown.ngAfterViewInit(); - dropdown.wrappedOptions.subscribe(unwrapper); - - sinon.assert.calledOnce(unwrapper); - sinon.assert.calledWith(unwrapper, options); - }); - - it('should leave the options untouched if already an observable', (): void => { - const unwrapper: Sinon.SinonSpy = sinon.spy(); - const optionsStream: BehaviorSubject = new BehaviorSubject(options); - dropdown.options = optionsStream; - - dropdown.ngAfterViewInit(); - dropdown.wrappedOptions.subscribe(unwrapper); - - sinon.assert.calledOnce(unwrapper); - sinon.assert.calledWith(unwrapper, options); - }); - }); - it('should set the value and close the options', (): void => { const closeSpy = sinon.spy(); dropdown.list = { diff --git a/source/components/inputs/select/select.ts b/source/components/inputs/select/select.ts index c0af3cb9..b0d765d4 100644 --- a/source/components/inputs/select/select.ts +++ b/source/components/inputs/select/select.ts @@ -1,6 +1,4 @@ import { Component, Optional, Input, Output, ViewChild, ContentChild, AfterViewInit, TemplateRef } from '@angular/core'; -import { Observable } from 'rxjs'; -import { isArray } from 'lodash'; import { services } from 'typescript-angular-utilities'; import __object = services.object; @@ -14,15 +12,18 @@ import { FormComponent } from '../../form/form'; import { BusyComponent } from '../../busy/busy'; import { POPOUT_LIST_PROVIDERS, PopoutListComponent } from '../../popoutList/index'; +import { baseAnimations } from '../input'; + @Component({ selector: 'rlSelect', template: require('./select.html'), inputs: validationInputs, outputs: baseOutputs, providers: [ComponentValidator, POPOUT_LIST_PROVIDERS], + animations: baseAnimations, }) export class SelectComponent extends ValidatedInputComponent implements AfterViewInit { - @Input() options: T[] | Observable; + @Input() options: T[]; @Input() transform: __transform.ITransform; @Input() nullOption: string; @@ -33,7 +34,6 @@ export class SelectComponent extends ValidatedInputComponent implements Af @ViewChild(PopoutListComponent) list: PopoutListComponent; @ContentChild(TemplateRef) template: TemplateRef; - wrappedOptions: Observable; private transformService: __transform.ITransformService; constructor(transformService: __transform.TransformService @@ -50,10 +50,6 @@ export class SelectComponent extends ValidatedInputComponent implements Af ngAfterViewInit(): void { super.ngAfterViewInit(); this.template = this.template || this.externalTemplate; - this.wrappedOptions = isArray(this.options) - ? Observable.of(this.options) - : >this.options; - this.busy.trigger(this.wrappedOptions); } select(value: T): void { diff --git a/source/components/inputs/signature/signature.tests.ts b/source/components/inputs/signature/signature.tests.ts index 9a2238ab..eb997793 100644 --- a/source/components/inputs/signature/signature.tests.ts +++ b/source/components/inputs/signature/signature.tests.ts @@ -1,3 +1,4 @@ +import { Observable } from 'rxjs'; import { fakeAsync, tick } from '@angular/core/testing'; import { SignatureComponent } from './signature'; @@ -14,8 +15,7 @@ describe('SignatureComponent', () => { beforeEach(() => { const validator: any = { - validate: sinon.spy(), - afterInit: sinon.spy(), + validate: sinon.spy(() => Observable.empty()), }; jqueryMock = sinon.spy(x => x); diff --git a/source/components/inputs/spinner/spinner.html b/source/components/inputs/spinner/spinner.html index 07d22d88..f5133a1f 100644 --- a/source/components/inputs/spinner/spinner.html +++ b/source/components/inputs/spinner/spinner.html @@ -1,26 +1,31 @@
- + [class.error]="componentValidator.error$ | async"> + -
- {{componentValidator.error}} + [placeholder]="label" + (focus)="showLabel()" + (blur)="hideLabelIfEmpty()" /> +
+ {{componentValidator.error$ | async}}
- + {{prefix}} + [placeholder]="label" + (focus)="showLabel()" + (blur)="hideLabelIfEmpty()" /> {{postfix}}
- \ No newline at end of file + diff --git a/source/components/inputs/spinner/spinner.ts b/source/components/inputs/spinner/spinner.ts index 6468e976..be45af7a 100644 --- a/source/components/inputs/spinner/spinner.ts +++ b/source/components/inputs/spinner/spinner.ts @@ -13,6 +13,8 @@ import { ValidatedInputComponent, validationInputs, baseOutputs, IInputChanges } import { ComponentValidator } from '../../../services/componentValidator/componentValidator.service'; import { FormComponent } from '../../form/form'; +import { baseAnimations } from '../input'; + export const defaultMaxValue: number = 100000000000000000000; export interface ISpinnerChanges extends IInputChanges { @@ -25,6 +27,7 @@ export interface ISpinnerChanges extends IInputChanges { inputs: validationInputs, outputs: baseOutputs, providers: [ComponentValidator], + animations: baseAnimations, }) export class SpinnerComponent extends ValidatedInputComponent implements AfterViewInit, OnChanges, AfterViewChecked { @Input() min: number; diff --git a/source/components/inputs/textarea/textarea.html b/source/components/inputs/textarea/textarea.html index f826cb74..3d62bb3a 100644 --- a/source/components/inputs/textarea/textarea.html +++ b/source/components/inputs/textarea/textarea.html @@ -1,15 +1,18 @@
- + [class.error]="componentValidator.error$ | async"> + -
- {{componentValidator.error}} +
+ {{componentValidator.error$ | async}}
-
\ No newline at end of file +
diff --git a/source/components/inputs/textarea/textarea.ts b/source/components/inputs/textarea/textarea.ts index 25df32b6..fd6456c7 100644 --- a/source/components/inputs/textarea/textarea.ts +++ b/source/components/inputs/textarea/textarea.ts @@ -9,12 +9,15 @@ import { ValidatedInputComponent, validationInputs, baseOutputs } from '../valid import { ComponentValidator } from '../../../services/componentValidator/componentValidator.service'; import { FormComponent } from '../../form/form'; +import { baseAnimations } from '../input'; + @Component({ selector: 'rlTextarea', template: require('./textarea.html'), inputs: validationInputs, outputs: baseOutputs, providers: [ComponentValidator], + animations: baseAnimations, }) export class TextareaComponent extends ValidatedInputComponent implements OnInit { @Input() maxlength: number; diff --git a/source/components/inputs/textbox/textbox.html b/source/components/inputs/textbox/textbox.html index 59110d0e..dd3645e9 100644 --- a/source/components/inputs/textbox/textbox.html +++ b/source/components/inputs/textbox/textbox.html @@ -1,15 +1,18 @@
- + [class.error]="componentValidator.error$ | async"> + -
- {{componentValidator.error}} +
+ {{componentValidator.error$ | async}}
-
\ No newline at end of file +
diff --git a/source/components/inputs/textbox/textbox.ts b/source/components/inputs/textbox/textbox.ts index 3136d2ac..0b03275c 100644 --- a/source/components/inputs/textbox/textbox.ts +++ b/source/components/inputs/textbox/textbox.ts @@ -9,12 +9,15 @@ import { ValidatedInputComponent, validationInputs, baseOutputs } from '../valid import { ComponentValidator } from '../../../services/componentValidator/componentValidator.service'; import { FormComponent } from '../../form/form'; +import { baseAnimations } from '../input'; + @Component({ selector: 'rlTextbox', template: require('./textbox.html'), inputs: validationInputs, outputs: baseOutputs, providers: [ComponentValidator], + animations: baseAnimations, }) export class TextboxComponent extends ValidatedInputComponent implements OnInit { @Input() maxlength: number; diff --git a/source/components/inputs/typeahead/typeahead.html b/source/components/inputs/typeahead/typeahead.html index d6e4520b..e213549e 100644 --- a/source/components/inputs/typeahead/typeahead.html +++ b/source/components/inputs/typeahead/typeahead.html @@ -1,17 +1,20 @@
- + [class.error]="componentValidator.error$ | async"> +
@@ -25,7 +28,7 @@
-
- {{componentValidator.error}} +
+ {{componentValidator.error$ | async}}
-
\ No newline at end of file +
diff --git a/source/components/inputs/typeahead/typeahead.tests.ts b/source/components/inputs/typeahead/typeahead.tests.ts index 2a3d183c..8a86eb07 100644 --- a/source/components/inputs/typeahead/typeahead.tests.ts +++ b/source/components/inputs/typeahead/typeahead.tests.ts @@ -1,3 +1,4 @@ +import { Observable } from 'rxjs'; import { rlFakeAsync, mock, IMockedRequest, rlTick, flushMicrotasks } from 'rl-async-testing'; import { services } from 'typescript-angular-utilities'; @@ -30,9 +31,8 @@ describe('TypeaheadComponent', () => { beforeEach(() => { const validator: any = { - setValidators: sinon.spy(), - validate: sinon.spy(), - afterInit: sinon.spy(), + initValidator: sinon.spy(), + validate: sinon.spy(() => Observable.empty()), }; typeahead = new TypeaheadComponent(__transform.transform, null, validator, __object.objectUtility, __array.arrayUtility, __guid.guid, __search.searchUtility); @@ -315,7 +315,7 @@ describe('TypeaheadComponent', () => { typeahead.searchStream.next('search'); rlTick(DEFAULT_SERVER_SEARCH_DEBOUNCE); flushMicrotasks(); - typeahead.visibleItems.subscribe(data => visibleItems = data); + typeahead.visibleItems$.subscribe(data => visibleItems = data); loadItems.flush(); loadItems.reset(); busy.trigger.reset(); @@ -353,7 +353,6 @@ describe('TypeaheadComponent', () => { flushMicrotasks(); sinon.assert.calledTwice(busy.trigger); - sinon.assert.calledWith(busy.trigger, typeahead.visibleItems); sinon.assert.calledOnce(loadItems); sinon.assert.calledWith(loadItems, 'search2'); diff --git a/source/components/inputs/typeahead/typeahead.ts b/source/components/inputs/typeahead/typeahead.ts index cc81a881..dc89b095 100644 --- a/source/components/inputs/typeahead/typeahead.ts +++ b/source/components/inputs/typeahead/typeahead.ts @@ -15,6 +15,8 @@ import { FormComponent } from '../../form/form'; import { BusyComponent } from '../../busy/busy'; import { POPOUT_LIST_PROVIDERS, PopoutListComponent } from '../../popoutList/index'; +import { baseAnimations } from '../input'; + export const DEFAULT_SERVER_SEARCH_DEBOUNCE: number = 500; export const DEFAULT_CLIENT_SEARCH_DEBOUNCE: number = 100; @@ -29,6 +31,7 @@ export interface ITypeaheadChanges { inputs: validationInputs, outputs: baseOutputs, providers: [ComponentValidator, POPOUT_LIST_PROVIDERS], + animations: baseAnimations, }) export class TypeaheadComponent extends ValidatedInputComponent implements OnInit, OnChanges { @Input() transform: __transform.ITransform; @@ -47,16 +50,21 @@ export class TypeaheadComponent extends ValidatedInputComponent implements searchStream: Subject = new Subject(); cachedItems: any[]; getItemsRequest: Observable; - visibleItems: Observable; loading: boolean = false; loadDelay: number; placeholder: string; allowCustomOption: boolean; collapsed: boolean = false; + private _visibleItems: BehaviorSubject; + transformService: __transform.ITransformService; searchUtility: __search.ISearchUtility; + get visibleItems$(): Observable { + return this._visibleItems.asObservable(); + } + get canShowOptions(): boolean { return !(this.busy.loading || !this.search); } @@ -77,6 +85,7 @@ export class TypeaheadComponent extends ValidatedInputComponent implements this.searchUtility = searchService; this.inputType = 'typeahead'; this.search = ''; + this._visibleItems = new BehaviorSubject(null); } add(item: T): void { @@ -117,13 +126,15 @@ export class TypeaheadComponent extends ValidatedInputComponent implements refresh(search: string): Observable { this.search = search; if (this.object.isNullOrEmpty(search)) { - this.visibleItems = Observable.empty(); - return this.visibleItems; + this._visibleItems.next([]); + return Observable.empty(); } const loadRequest: Observable = this.loadItems(search); this.busy.trigger(loadRequest); - this.visibleItems = loadRequest; - loadRequest.subscribe(() => this.list.open()); + loadRequest.subscribe(data => { + this.list.open(); + this._visibleItems.next(data); + }); return loadRequest; } @@ -199,7 +210,7 @@ export class TypeaheadComponent extends ValidatedInputComponent implements private showCustomSearch(search: string): boolean { return this.allowCustomOption - && !find(this.visibleItems, (item: any): boolean => { + && !find(this._visibleItems.getValue(), (item: any): boolean => { return this.getDisplayName(item) === search; }); } diff --git a/source/components/inputs/typeaheadList/typeaheadList.tests.ts b/source/components/inputs/typeaheadList/typeaheadList.tests.ts index a82ef68a..0ad27127 100644 --- a/source/components/inputs/typeaheadList/typeaheadList.tests.ts +++ b/source/components/inputs/typeaheadList/typeaheadList.tests.ts @@ -1,3 +1,4 @@ +import { Observable } from 'rxjs'; import { rlFakeAsync, mock, IMockedRequest } from 'rl-async-testing'; import { services } from 'typescript-angular-utilities'; @@ -24,9 +25,8 @@ describe('TypeaheadListComponent', () => { beforeEach(() => { const validator: any = { - setValidators: sinon.spy(), - validate: sinon.spy(), - afterInit: sinon.spy(), + initValidator: sinon.spy(), + validate: sinon.spy(() => Observable.empty()), }; items = [ diff --git a/source/components/inputs/userRating/userRating.html b/source/components/inputs/userRating/userRating.html index 33ee450c..412f3fb1 100644 --- a/source/components/inputs/userRating/userRating.html +++ b/source/components/inputs/userRating/userRating.html @@ -1,8 +1,12 @@ - + - \ No newline at end of file +
+ {{componentValidator.error$ | async}} +
+
diff --git a/source/components/inputs/userRating/userRating.tests.ts b/source/components/inputs/userRating/userRating.tests.ts index 7d336f6e..62ce2b6d 100644 --- a/source/components/inputs/userRating/userRating.tests.ts +++ b/source/components/inputs/userRating/userRating.tests.ts @@ -1,5 +1,8 @@ -import { services } from 'typescript-angular-utilities'; +import { Observable, Subject } from 'rxjs'; + +import { services } from 'typescript-angular-utilities'; import __object = services.object; +import __array = services.array; import __guid = services.guid; import { UserRatingComponent } from './userRating'; @@ -7,11 +10,18 @@ import { UserRatingComponent } from './userRating'; describe('UserRatingComponent', () => { let userRating: UserRatingComponent; let setValue: Sinon.SinonSpy; + let control: any; beforeEach(() => { - userRating = new UserRatingComponent({}, null, __object.objectUtility, __guid.guid); + const validator = { + validate: sinon.spy(() => Observable.empty()), + initValidator: sinon.spy(), + }; + userRating = new UserRatingComponent({}, null, validator, __object.objectUtility, __array.arrayUtility, __guid.guid); - setValue = sinon.spy(); + control = { valueChanges: new Subject() }; + userRating.control = control; + setValue = sinon.spy(value => control.valueChanges.next(value)); userRating.setValue = setValue; }); @@ -51,4 +61,16 @@ describe('UserRatingComponent', () => { expect(userRating.stars[3].filled).to.be.true; expect(userRating.stars[4].filled).to.be.true; }); + + it('should update the view state with external changes', () => { + userRating.ngOnInit(); + + control.valueChanges.next(2); + + expect(userRating.stars[0].filled).to.be.false; + expect(userRating.stars[1].filled).to.be.false; + expect(userRating.stars[2].filled).to.be.false; + expect(userRating.stars[3].filled).to.be.true; + expect(userRating.stars[4].filled).to.be.true; + }); }); diff --git a/source/components/inputs/userRating/userRating.ts b/source/components/inputs/userRating/userRating.ts index 27e85878..dbbdcb52 100644 --- a/source/components/inputs/userRating/userRating.ts +++ b/source/components/inputs/userRating/userRating.ts @@ -8,7 +8,8 @@ import __guid = services.guid; import { DefaultTheme } from '../../componentsDefaultTheme'; -import { InputComponent, baseInputs, baseOutputs } from '../input'; +import { ValidatedInputComponent, validationInputs, baseOutputs } from '../validationInput'; +import { ComponentValidator } from '../../../services/componentValidator/componentValidator.service'; import { FormComponent } from '../../form/form'; export interface IStar { @@ -19,10 +20,11 @@ export interface IStar { @Component({ selector: 'rlUserRating', template: require('./userRating.html'), - inputs: baseInputs, + inputs: validationInputs, outputs: baseOutputs, + providers: [ComponentValidator], }) -export class UserRatingComponent extends InputComponent implements OnInit { +export class UserRatingComponent extends ValidatedInputComponent implements OnInit { @Input() range: number; stars: IStar[]; @@ -31,9 +33,11 @@ export class UserRatingComponent extends InputComponent implements OnIni constructor(defaultTheme: DefaultTheme , @Optional() rlForm: FormComponent + , componentValidator: ComponentValidator , object: __object.ObjectUtility + , array: __array.ArrayUtility , guid: __guid.GuidService) { - super(rlForm, object, guid); + super(rlForm, componentValidator, object, array, guid); this.inputType = 'userRating'; this.initControl(); this.useDefaultTheme = defaultTheme.useDefaultTheme; @@ -49,11 +53,11 @@ export class UserRatingComponent extends InputComponent implements OnIni }; }); this.updateStarView(this.value); + this.control.valueChanges.subscribe(value => this.updateStarView(value)); } setRating(rating: number): void { this.setValue(rating); - this.updateStarView(rating); } private updateStarView(rating: number): void { @@ -65,4 +69,4 @@ export class UserRatingComponent extends InputComponent implements OnIni } }); } -} \ No newline at end of file +} diff --git a/source/components/inputs/validationInput.tests.ts b/source/components/inputs/validationInput.tests.ts index 757a4961..6fc4a481 100644 --- a/source/components/inputs/validationInput.tests.ts +++ b/source/components/inputs/validationInput.tests.ts @@ -1,4 +1,4 @@ -import { Subject } from 'rxjs'; +import { Subject, Observable } from 'rxjs'; import { services } from 'typescript-angular-utilities'; import __object = services.object; import __array = services.array; @@ -14,8 +14,7 @@ interface IControlMock { } interface IComponentValidatorMock { - setValidators: Sinon.SinonSpy; - afterInit: Sinon.SinonSpy; + initValidator: Sinon.SinonSpy; validate: Sinon.SinonSpy; } @@ -25,9 +24,8 @@ describe('ValidatedInputComponent', (): void => { beforeEach((): void => { componentValidator = { - setValidators: sinon.spy(), - afterInit: sinon.spy(), - validate: sinon.spy(), + initValidator: sinon.spy(), + validate: sinon.spy(() => Observable.empty()), }; input = new ValidatedInputComponent(null, componentValidator, __object.objectUtility, __array.arrayUtility, __guid.guid); @@ -41,8 +39,8 @@ describe('ValidatedInputComponent', (): void => { input.ngOnInit(); - sinon.assert.calledOnce(componentValidator.setValidators); - sinon.assert.calledWith(componentValidator.setValidators, [1, 2, 3, 4]); + sinon.assert.calledOnce(componentValidator.initValidator); + sinon.assert.calledWith(componentValidator.initValidator, [1, 2, 3, 4]); }); it('should arrayify the validators if necessary', (): void => { @@ -51,8 +49,8 @@ describe('ValidatedInputComponent', (): void => { input.ngOnInit(); - sinon.assert.calledOnce(componentValidator.setValidators); - sinon.assert.calledWith(componentValidator.setValidators, [1, 2]); + sinon.assert.calledOnce(componentValidator.initValidator); + sinon.assert.calledWith(componentValidator.initValidator, [1, 2]); }); it('should build a required validator if rlRequired is specified', (): void => { @@ -60,10 +58,9 @@ describe('ValidatedInputComponent', (): void => { input.ngOnInit(); - sinon.assert.calledOnce(componentValidator.setValidators); - const validator: __validation.IValidationHandler = componentValidator.setValidators.firstCall.args[0][0]; + sinon.assert.calledOnce(componentValidator.initValidator); + const validator: __validation.IObservableValidationHandler = componentValidator.initValidator.firstCall.args[0][0]; expect(validator.name).to.equal('rlRequired'); - expect(validator.errorMessage).to.equal('This is required'); }); it('should set the control on the component validator and update the validity of the control', (): void => { @@ -76,8 +73,6 @@ describe('ValidatedInputComponent', (): void => { input.ngAfterViewInit(); - sinon.assert.calledOnce(componentValidator.afterInit); - sinon.assert.calledWith(componentValidator.afterInit, control); sinon.assert.calledOnce(control.updateValueAndValidity); sinon.assert.calledWith(control.updateValueAndValidity, 4); }); diff --git a/source/components/inputs/validationInput.ts b/source/components/inputs/validationInput.ts index b2f21005..9673a2ee 100644 --- a/source/components/inputs/validationInput.ts +++ b/source/components/inputs/validationInput.ts @@ -1,5 +1,6 @@ import { AfterViewInit, OnInit, OnChanges, SimpleChange } from '@angular/core'; import { FormControl } from '@angular/forms'; +import { Observable, BehaviorSubject } from 'rxjs'; import { services } from 'typescript-angular-utilities'; import __validation = services.validation; @@ -20,8 +21,9 @@ export interface IInputChanges { } export class ValidatedInputComponent extends InputComponent implements AfterViewInit, OnInit, OnChanges { - validator: __validation.IValidationHandler; - validators: __validation.IValidationHandler[]; + value$: BehaviorSubject; + validator: __validation.IObservableValidationHandler; + validators: __validation.IObservableValidationHandler[]; rlRequired: string; protected componentValidator: ComponentValidator; @@ -35,14 +37,17 @@ export class ValidatedInputComponent extends InputComponent implements Aft super(rlForm, object, guid); this.array = array; this.componentValidator = componentValidator; - this.control = new FormControl('', this.componentValidator.validate.bind(this.componentValidator)); + this.control = new FormControl('', null, this.componentValidator.validate.bind(this.componentValidator)); this.initControl(); } ngOnInit(): void { super.ngOnInit(); - let validators: __validation.IValidationHandler[] = []; + this.value$ = new BehaviorSubject(this.value); + this.control.valueChanges.subscribe(this.value$); + + let validators: __validation.IObservableValidationHandler[] = []; if (this.validator) { validators = validators.concat(this.array.arrayify(this.validator)); @@ -55,16 +60,15 @@ export class ValidatedInputComponent extends InputComponent implements Aft if (this.rlRequired) { validators.push({ name: 'rlRequired', - validate: (value: any): boolean => { return !this.object.isNullOrEmpty(value); }, - errorMessage: this.rlRequired, + validate: (value$: Observable): Observable => { + return value$.map(value => value ? null : this.rlRequired); + }, }); } - - this.componentValidator.setValidators(validators); + this.componentValidator.initValidator(validators, this.value$, this.control); } ngAfterViewInit(): void { - this.componentValidator.afterInit(this.control); this.control.updateValueAndValidity(this.value || undefined); super.ngAfterViewInit(); diff --git a/source/components/messageLog/messageLog.directive.tests.ts b/source/components/messageLog/messageLog.directive.tests.ts index b0598371..e91c5c4a 100644 --- a/source/components/messageLog/messageLog.directive.tests.ts +++ b/source/components/messageLog/messageLog.directive.tests.ts @@ -301,6 +301,7 @@ describe('messageLog', () => { scope = controllerResult.scope; log = controllerResult.controller; + log.$onInit(); } }); diff --git a/source/components/messageLog/messageLog.directive.ts b/source/components/messageLog/messageLog.directive.ts index e9569e3d..368fdf1d 100644 --- a/source/components/messageLog/messageLog.directive.ts +++ b/source/components/messageLog/messageLog.directive.ts @@ -68,23 +68,25 @@ export class MessageLogController implements IMessageLogBindings { static $inject: string[] = [__dialog.serviceName, '$scope', factoryName]; - constructor(private dialog: __dialog.IDialogService, $scope: ng.IScope, messageLogFactory: IMessageLogFactory) { - this.messageLog = this.messageLogBinding || messageLogFactory.getInstance(); + constructor(private dialog: __dialog.IDialogService, private $scope: ng.IScope, private messageLogFactory: IMessageLogFactory) {} - $scope.$watch((): IMessage[] => { return this.messageLog.visibleMessages; } + $onInit() { + this.messageLog = this.messageLogBinding || this.messageLogFactory.getInstance(); + + this.$scope.$watch((): IMessage[] => { return this.messageLog.visibleMessages; } , (value: IMessage[]): void => { this.messages = value; }); - $scope.$watch((): boolean => { return this.messageLog.hasForwardMessages; }, (value: boolean): void => { + this.$scope.$watch((): boolean => { return this.messageLog.hasForwardMessages; }, (value: boolean): void => { this.hasNextPage = value; }); - $scope.$watch((): boolean => { return this.messageLog.hasBackwardMessages; }, (value: boolean): void => { + this.$scope.$watch((): boolean => { return this.messageLog.hasBackwardMessages; }, (value: boolean): void => { this.hasPreviousPage = value; }); - $scope.$watch((): boolean => { return this.messageLog.busy; }, (value: boolean): void => { + this.$scope.$watch((): boolean => { return this.messageLog.busy; }, (value: boolean): void => { if (!value) { this.loading = false; this.loadingInitial = false; @@ -93,7 +95,7 @@ export class MessageLogController implements IMessageLogBindings { } }); - $scope.$watch((): IMessageLogDataService => { return this.service; }, (service: IMessageLogDataService): void => { + this.$scope.$watch((): IMessageLogDataService => { return this.service; }, (service: IMessageLogDataService): void => { this.messageLog.dataService = service; this.loadingInitial = true; }); diff --git a/source/components/multiStepIndicator/multiStepIndicator.ng1.html b/source/components/multiStepIndicator/multiStepIndicator.ng1.html deleted file mode 100644 index 05faaae0..00000000 --- a/source/components/multiStepIndicator/multiStepIndicator.ng1.html +++ /dev/null @@ -1,16 +0,0 @@ -
-
    -
  1. -
    -

    {{step.count()}}

    -

    {{step.title}}

    -

    {{step.subtitle}}

    -
    -
  2. -
-
\ No newline at end of file diff --git a/source/components/multiStepIndicator/multiStepIndicator.ng1.ts b/source/components/multiStepIndicator/multiStepIndicator.ng1.ts deleted file mode 100644 index 12864a30..00000000 --- a/source/components/multiStepIndicator/multiStepIndicator.ng1.ts +++ /dev/null @@ -1,124 +0,0 @@ -import * as angular from 'angular'; -import * as _ from 'lodash'; - -import { services, downgrade } from 'typescript-angular-utilities'; -import __object = services.object; - -export var moduleName: string = 'rl.ui.components.multiStepIndicator'; -export var componentName: string = 'rlMultiStepIndicator'; -export var controllerName: string = 'MultiStepIndicatorController'; - -export interface IStep { - title: string; - subtitle?: string; - onClick?: {(): angular.IPromise | void}; - stateName?: string; - count?: {(): number}; - isCompleted?: boolean | {(): boolean}; - isValid?: boolean | {(): boolean}; - isCurrent?: boolean; -} - -export interface IConfiguredStep extends IStep { - inactive: boolean; - loading: boolean; - hasCount: boolean; - getCompleted(): boolean; - getValid(): boolean; -} - -export class MultiStepIndicatorController { - steps: IConfiguredStep[]; - - static $inject: string[] = ['$state', '$q', downgrade.objectServiceName]; - constructor(private $state: angular.ui.IStateService - , private $q: angular.IQService - , private object: __object.IObjectUtility) { - this.configureSteps(); - } - - onClick(step: IConfiguredStep): void { - if (!this.anyLoading()) { - step.loading = true; - this.$q.when(step.onClick()).then((): void => { - step.loading = false; - }); - } - } - - anyLoading(): boolean { - return _.some(this.steps, (step: IConfiguredStep): boolean => { - return step.loading; - }); - } - - private configureSteps(): void { - _.each(this.steps, (step: IConfiguredStep): void => { - step.hasCount = _.isFunction(step.count); - step.getCompleted = (): boolean => { return this.getIsCompleted(step); }; - step.getValid = (): boolean => { return this.getIsValid(step); }; - - if (!_.isFunction(step.onClick)) { - if (this.object.isNullOrWhitespace(step.stateName)) { - step.inactive = true; - } else { - step.onClick = (): angular.IPromise => { return this.redirectToState(step); }; - - if (this.$state.includes(step.stateName)) { - step.isCurrent = true; - } - } - } - }); - } - - private redirectToState(step: IConfiguredStep): angular.IPromise { - return this.$state.go(step.stateName).then((): void => { - this.clearCurrentState(); - step.isCurrent = true; - }); - } - - private clearCurrentState(): void { - _.each(this.steps, (step: IStep): void => { - step.isCurrent = false; - }); - } - - private getIsCompleted(step: IConfiguredStep): boolean { - return _.isFunction(step.isCompleted) - ? (<{(): boolean}>step.isCompleted)() - : step.isCompleted; - } - - private setIsCompleted(step: IConfiguredStep, isCompleted: boolean): void { - if (!_.isFunction(step.isCompleted)) { - step.isCompleted = isCompleted; - } - } - - private getIsValid(step: IConfiguredStep): boolean { - if (_.isFunction(step.isValid)) { - return (<{(): boolean}>step.isValid)(); - } else if (!_.isUndefined(step.isValid != null)) { - return step.isValid; - } else { - return true; - } - } -} - -let multiStepIndicator: angular.IComponentOptions = { - template: require('./multiStepIndicator.ng1.html'), - controller: controllerName, - controllerAs: 'breadcrumb', - bindings: { - steps: '=', - numbered: '=', - checked: '=', - }, -}; - -angular.module(moduleName, [downgrade.moduleName]) - .component(componentName, multiStepIndicator) - .controller(controllerName, MultiStepIndicatorController); diff --git a/source/components/multiStepIndicator/multiStepIndicator.tests.ng1.ts b/source/components/multiStepIndicator/multiStepIndicator.tests.ng1.ts deleted file mode 100644 index 713bbbf7..00000000 --- a/source/components/multiStepIndicator/multiStepIndicator.tests.ng1.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { services } from 'typescript-angular-utilities'; -import test = services.test; - -import { - moduleName, - controllerName, - MultiStepIndicatorController, - IStep, - IConfiguredStep, -} from './multiStepIndicator.ng1'; - -import * as angular from 'angular'; -import 'angular-mocks'; - -interface IStateServiceMock { - go: Sinon.SinonSpy; - includes: Sinon.SinonSpy; -} - -describe('MultiStepIndicatorController', () => { - let scope: angular.IScope; - let multiStepIndicator: MultiStepIndicatorController; - let stateMock: IStateServiceMock; - let $q: angular.IQService; - - beforeEach(() => { - angular.mock.module(moduleName); - - let services: any = test.angularFixture.inject('$q'); - $q = services.$q; - - stateMock = { - go: sinon.spy((): angular.IPromise => { return $q.when(); }), - includes: sinon.spy((): boolean => { return false; }), - }; - }); - - it('should set inactive to true if no click handler or state name is provided', (): void => { - let step: IStep = {}; - buildController([step]); - expect((step).inactive).to.be.true; - }); - - it('should provide a default click handler that redirects to the specified state and sets the step to current if a state name is provided', (): void => { - let step: IStep = { stateName: 'state' }; - buildController([step]); - - step.onClick(); - - sinon.assert.calledOnce(stateMock.go); - sinon.assert.calledWith(stateMock.go, 'state'); - - scope.$digest(); - - expect(step.isCurrent).to.be.true; - }); - - it('should set the step to current if the specified state is already active', (): void => { - let step1: IStep = { stateName: 'state2', isCurrent: false }; - let step2: IStep = { stateName: 'state1', isCurrent: false }; - stateMock.includes = sinon.spy((name: string): boolean => { return name === step1.stateName; }); - buildController([step1, step2]); - - expect(step1.isCurrent).to.be.true; - expect(step2.isCurrent).to.be.false; - }); - - it('should show a spinner on the step and disable all clicks when the step is loading', (): void => { - let step1: IConfiguredStep = { onClick: sinon.spy(), }; - let step2: IConfiguredStep = { onClick: sinon.spy(), }; - buildController([step1, step2]); - - multiStepIndicator.onClick(step1); - - sinon.assert.calledOnce(step1.onClick); - expect(step1.loading).to.be.true; - - multiStepIndicator.onClick(step2); - - sinon.assert.notCalled(step2.onClick); - }); - - it('should clear the spinner when the promise resolves', (): void => { - let step1: IConfiguredStep = { onClick: sinon.spy(), }; - buildController([step1]); - - multiStepIndicator.onClick(step1); - - sinon.assert.calledOnce(step1.onClick); - expect(step1.loading).to.be.true; - - scope.$digest(); - - expect(step1.loading).to.be.false; - }); - - it('should allow for specifying isCompleted as a bool or a function', (): void => { - let step1: IConfiguredStep = { isCompleted: true, }; - let step2: IConfiguredStep = { isCompleted: sinon.spy((): boolean => { return true; }), }; - buildController([step1, step2]); - - expect(step1.getCompleted()).to.be.true; - expect(step2.getCompleted()).to.be.true; - - sinon.assert.calledOnce(step2.isCompleted); - }); - - function buildController(steps: IStep[]): void { - let controllerResult: test.IControllerResult - = test.angularFixture.controllerWithBindings(controllerName, { steps: steps }, { $state: stateMock }); - - scope = controllerResult.scope; - multiStepIndicator = controllerResult.controller; - } -}); diff --git a/source/components/multiStepIndicator/multiStepIndicator.tests.ts b/source/components/multiStepIndicator/multiStepIndicator.tests.ts index d338b90c..19bcb276 100644 --- a/source/components/multiStepIndicator/multiStepIndicator.tests.ts +++ b/source/components/multiStepIndicator/multiStepIndicator.tests.ts @@ -1,19 +1,26 @@ -import * as ui from 'angular-ui-router'; -import { rlFakeAsync, mock, IMockedPromise } from 'rl-async-testing'; +import { Subject } from 'rxjs'; +import { rlFakeAsync, rlTick, mock, IMockedPromise } from 'rl-async-testing'; import { MultiStepIndicatorComponent, IStep, IConfiguredStep } from './multiStepIndicator'; +interface IRouterMock { + navigate: IMockedPromise; + isActive: Sinon.SinonSpy; + createUrlTree: Sinon.SinonSpy; +} + describe('MultiStepIndicatorComponent', () => { let msi: MultiStepIndicatorComponent; - let stateMock: any; + let routerMock: IRouterMock; beforeEach(() => { - stateMock = { - go: mock.promise(), - includes: sinon.spy(), + routerMock = { + navigate: mock.promise(), + isActive: sinon.spy(() => true), + createUrlTree: sinon.spy(array => array[0]), }; - msi = new MultiStepIndicatorComponent(stateMock); + msi = new MultiStepIndicatorComponent(routerMock); }); it('should set isActive to false if neither a click handler nor state name are provided', (): void => { @@ -26,7 +33,7 @@ describe('MultiStepIndicatorComponent', () => { }); it('should set isActive to true if both a click handler and state name are provided', (): void => { - let step: IStep = { onClick: () => mock.promise(), stateName: 'state' }; + let step: IStep = { onClick: () => mock.promise(), routerLink: ['state'] }; msi.steps = [step]; msi.ngOnInit(); @@ -35,27 +42,27 @@ describe('MultiStepIndicatorComponent', () => { }); it('should provide a default click handler that redirects to the specified state and sets the step to current if a state name is provided', rlFakeAsync((): void => { - let step: IStep = { stateName: 'state' }; + let step: IStep = { routerLink: ['state'] }; msi.steps = [step]; msi.ngOnInit(); - step.onClick(); + msi.onClick(step); - sinon.assert.calledOnce(stateMock.go); - sinon.assert.calledWith(stateMock.go, 'state'); + sinon.assert.calledOnce(routerMock.navigate); + sinon.assert.calledWith(routerMock.navigate, ['state']); - stateMock.go.flush(); + routerMock.navigate.flush(); expect(step.isCurrent).to.be.true; })); it('should set the step to current if the specified state is already active', (): void => { let activeState = 'activeState'; - let step1: IStep = { stateName: activeState }; - let step2: IStep = { stateName: 'inactiveState' }; + let step1: IStep = { routerLink: [activeState] }; + let step2: IStep = { routerLink: ['inactiveState'] }; - stateMock.includes = sinon.spy((name: string): boolean => name === activeState); + routerMock.isActive = sinon.spy((name: string): boolean => name === activeState); msi.steps = [step1, step2]; msi.ngOnInit(); @@ -98,25 +105,6 @@ describe('MultiStepIndicatorComponent', () => { expect((step).isLoading).to.be.false; })); - it('should clear the spinner when the promise rejects', rlFakeAsync((): void => { - const fakeError = 'fakeError'; - let step: IStep = { onClick: mock.rejectedPromise(fakeError) }; - - msi.steps = [step]; - msi.ngOnInit(); - - msi.onClick(step).catch((error) => { - expect(error).to.equal(fakeError); - }); - - expect((step).isLoading).to.be.true; - - (>step.onClick).flush(); - - sinon.assert.calledOnce(step.onClick); - expect((step).isLoading).to.be.false; - })); - it('should allow isCompleted to be supplied as a bool or a function', (): void => { let step1: IStep = { isCompleted: true, }; let step2: IStep = { isCompleted: sinon.spy((): boolean => { return true; }), }; diff --git a/source/components/multiStepIndicator/multiStepIndicator.ts b/source/components/multiStepIndicator/multiStepIndicator.ts index 610a0aff..b8130193 100644 --- a/source/components/multiStepIndicator/multiStepIndicator.ts +++ b/source/components/multiStepIndicator/multiStepIndicator.ts @@ -1,12 +1,13 @@ -import { Component, Inject, Input, OnInit } from '@angular/core'; -import * as ui from 'angular-ui-router'; -import * as _ from 'lodash'; +import { Component, Input, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { each, some, isFunction, isUndefined } from 'lodash'; export interface IStep { title: string; subtitle?: string; - onClick?: {(): Promise}; - stateName?: string; + onClick?: {(): Observable}; + routerLink?: any[]; count?: {(): number}; isCompleted?: boolean | {(): boolean}; isValid?: boolean | {(): boolean}; @@ -29,49 +30,46 @@ export class MultiStepIndicatorComponent implements OnInit { @Input() numbered: boolean; @Input() checked: boolean; - private _state: ui.IStateService; + private router: Router; - constructor(@Inject('$state') state: ui.IStateService) { - this._state = state; + constructor(router: Router) { + this.router = router; } ngOnInit() { this.configureSteps(); } - onClick(step: IConfiguredStep): Promise { + onClick(step: IConfiguredStep): Observable { if (!this.anyLoading()) { step.isLoading = true; - return step.onClick().then((): void => { - step.isLoading = false; - }).catch((error) => { - step.isLoading = false; - throw error; - }); + const stream = Observable.from(step.onClick()); + stream.subscribe({ complete: () => step.isLoading = false }); + return stream; } - return null; + return Observable.empty(); } anyLoading(): boolean { - return _.some(this.steps, (step: IConfiguredStep): boolean => { + return some(this.steps, (step: IConfiguredStep): boolean => { return step.isLoading; }); } private configureSteps(): void { - _.each(this.steps, (step: IConfiguredStep): void => { + each(this.steps, (step: IConfiguredStep): void => { step.getCompleted = (): boolean => this.getIsCompleted(step); step.getValid = (): boolean => this.getIsValid(step); step.isActive = true; step.isCurrent = false; step.isLoading = false; - if (!_.isFunction(step.onClick)) { - if (step.stateName) { - step.onClick = (): Promise => this.redirectToState(step); + if (!isFunction(step.onClick)) { + if (step.routerLink) { + step.onClick = (): Observable => this.redirectToState(step); - if (this._state.includes(step.stateName)) { + if (this.router.isActive(this.router.createUrlTree(step.routerLink), false)) { step.isCurrent = true; } } @@ -82,35 +80,37 @@ export class MultiStepIndicatorComponent implements OnInit { }); } - private redirectToState(step: IConfiguredStep): Promise { - return this._state.go(step.stateName).then((): void => { + private redirectToState(step: IConfiguredStep): Observable { + const stream = Observable.fromPromise(this.router.navigate(step.routerLink)); + stream.subscribe((): void => { this.clearCurrentState(); step.isCurrent = true; }); + return stream.map(() => null); } private clearCurrentState(): void { - _.each(this.steps, (step: IStep): void => { + each(this.steps, (step: IStep): void => { step.isCurrent = false; }); } private getIsCompleted(step: IConfiguredStep): boolean { - return _.isFunction(step.isCompleted) + return isFunction(step.isCompleted) ? (<{(): boolean}>step.isCompleted)() : step.isCompleted; } private setIsCompleted(step: IConfiguredStep, isCompleted: boolean): void { - if (!_.isFunction(step.isCompleted)) { + if (!isFunction(step.isCompleted)) { step.isCompleted = isCompleted; } } private getIsValid(step: IConfiguredStep): boolean { - if (_.isFunction(step.isValid)) { + if (isFunction(step.isValid)) { return (<{(): boolean}>step.isValid)(); - } else if (!_.isUndefined(step.isValid != null)) { + } else if (!isUndefined(step.isValid != null)) { return step.isValid; } else { return true; diff --git a/source/components/multiStepIndicator/step.component.html b/source/components/multiStepIndicator/step.component.html new file mode 100644 index 00000000..687b4440 --- /dev/null +++ b/source/components/multiStepIndicator/step.component.html @@ -0,0 +1,8 @@ +
  • +
    +

    {{title}}

    +
    +
  • diff --git a/source/components/multiStepIndicator/step.component.ts b/source/components/multiStepIndicator/step.component.ts new file mode 100644 index 00000000..e8118afc --- /dev/null +++ b/source/components/multiStepIndicator/step.component.ts @@ -0,0 +1,19 @@ +import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'rlStep', + template: require('./step.component.html'), + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class StepComponent { + @Input() title: string; + @Input() link: any[] | string; + @Input() valid: boolean; + @Input() useMsiStyling: boolean; + + get stepClass(): string { + return this.useMsiStyling + ? 'rl-multi-step-item' + : 'rl-tab-item'; + } +} diff --git a/source/components/popoutList/popoutList.html b/source/components/popoutList/popoutList.html index 38d40414..5b2a11c4 100644 --- a/source/components/popoutList/popoutList.html +++ b/source/components/popoutList/popoutList.html @@ -1,10 +1,10 @@ -
      +
        - {{getDisplayName(option)}} -
      \ No newline at end of file +
    diff --git a/source/components/popoutList/popoutList.tests.ts b/source/components/popoutList/popoutList.tests.ts index d999d112..1dfdc4e7 100644 --- a/source/components/popoutList/popoutList.tests.ts +++ b/source/components/popoutList/popoutList.tests.ts @@ -30,7 +30,7 @@ describe('PopoutListComponent', () => { list = new PopoutListComponent(transformService, listService); options = ['Option 1', 'Option 2', 'Option 3']; - list.options = Observable.of(options); + list.options = options; }); it('should emit a select event when a select is triggered on the list service', (): void => { diff --git a/source/components/popoutList/popoutList.ts b/source/components/popoutList/popoutList.ts index 422b8da1..50400e6b 100644 --- a/source/components/popoutList/popoutList.ts +++ b/source/components/popoutList/popoutList.ts @@ -13,7 +13,7 @@ import { PopoutListService } from './popoutList.service'; template: require('./popoutList.html'), }) export class PopoutListComponent { - @Input() options: Observable; + @Input() options: T[]; @Input() template: TemplateRef; @Input() transform: __transform.ITransform; @Output() select: EventEmitter = new EventEmitter(); @@ -39,10 +39,8 @@ export class PopoutListComponent { popoutListService.select.subscribe(value => this.select.emit(value)); } - get isEmpty(): Observable { - return this.options - ? this.options.map(x => !(x || x.length)) - : Observable.of(true); + get isEmpty(): boolean { + return !(this.options && this.options.length); } get showOptions(): boolean { diff --git a/source/components/validationGroup/validationGroup.html b/source/components/validationGroup/validationGroup.html index 8d9ec65d..a27594bb 100644 --- a/source/components/validationGroup/validationGroup.html +++ b/source/components/validationGroup/validationGroup.html @@ -1,6 +1,6 @@
    - {{groupValidator.error}} + {{groupValidator.error$ | async}}
    -
    \ No newline at end of file +
    diff --git a/source/components/validationGroup/validationGroup.tests.ts b/source/components/validationGroup/validationGroup.tests.ts index b1f5b912..34ade9be 100644 --- a/source/components/validationGroup/validationGroup.tests.ts +++ b/source/components/validationGroup/validationGroup.tests.ts @@ -1,3 +1,4 @@ +import { Observable } from 'rxjs'; import { services } from 'typescript-angular-utilities'; import __array = services.array; import __validation = services.validation; @@ -9,8 +10,7 @@ interface IControlMock { } interface IComponentValidatorMock { - setValidators: Sinon.SinonSpy; - afterInit: Sinon.SinonSpy; + initValidator: Sinon.SinonSpy; validate: Sinon.SinonSpy; } @@ -20,9 +20,8 @@ describe('ValidationGroupComponent', (): void => { beforeEach((): void => { componentValidator = { - setValidators: sinon.spy(), - afterInit: sinon.spy(), - validate: sinon.spy(), + initValidator: sinon.spy(), + validate: sinon.spy(() => Observable.empty()), }; group = new ValidationGroupComponent(null, componentValidator, __array.arrayUtility); @@ -48,8 +47,8 @@ describe('ValidationGroupComponent', (): void => { group.ngOnInit(); - sinon.assert.calledOnce(componentValidator.setValidators); - sinon.assert.calledWith(componentValidator.setValidators, [1, 2, 3, 4]); + sinon.assert.calledOnce(componentValidator.initValidator); + sinon.assert.calledWith(componentValidator.initValidator, [1, 2, 3, 4]); }); it('should arrayify the validators if necessary', (): void => { @@ -58,8 +57,8 @@ describe('ValidationGroupComponent', (): void => { group.ngOnInit(); - sinon.assert.calledOnce(componentValidator.setValidators); - sinon.assert.calledWith(componentValidator.setValidators, [1, 2]); + sinon.assert.calledOnce(componentValidator.initValidator); + sinon.assert.calledWith(componentValidator.initValidator, [1, 2]); }); it('should set the control on the component validator and update the validity of the control', (): void => { @@ -69,8 +68,6 @@ describe('ValidationGroupComponent', (): void => { group.ngAfterViewInit(); - sinon.assert.calledOnce(componentValidator.afterInit); - sinon.assert.calledWith(componentValidator.afterInit, control); sinon.assert.calledOnce(control.updateValueAndValidity); sinon.assert.calledWith(control.updateValueAndValidity, 4); }); @@ -109,4 +106,4 @@ describe('ValidationGroupComponent', (): void => { sinon.assert.calledOnce(control.updateValueAndValidity); sinon.assert.calledWith(control.updateValueAndValidity, 4); }); -}); \ No newline at end of file +}); diff --git a/source/components/validationGroup/validationGroup.ts b/source/components/validationGroup/validationGroup.ts index 1063a114..c020acd5 100644 --- a/source/components/validationGroup/validationGroup.ts +++ b/source/components/validationGroup/validationGroup.ts @@ -20,8 +20,8 @@ export interface IGroupChanges { providers: [ComponentValidator], }) export class ValidationGroupComponent implements OnInit, AfterViewInit, OnChanges { - @Input() validator: __validation.IValidationHandler; - @Input() validators: __validation.IValidationHandler[]; + @Input() validator: __validation.IObservableValidationHandler; + @Input() validators: __validation.IObservableValidationHandler[]; @Input() model: any; groupValidator: ComponentValidator; @@ -34,7 +34,7 @@ export class ValidationGroupComponent implements OnInit, AfterViewInit, OnChange , arrayUtility: __array.ArrayUtility) { this.arrayUtility = arrayUtility; this.groupValidator = componentValidator; - this.validationControl = new FormControl('', this.groupValidator.validate.bind(this.groupValidator)); + this.validationControl = new FormControl('', null, this.groupValidator.validate.bind(this.groupValidator)); this.formGroup = new FormGroup({ validation: this.validationControl }); if (rlForm) { rlForm.form.rlNestedFormGroups.push(this.formGroup); @@ -42,7 +42,7 @@ export class ValidationGroupComponent implements OnInit, AfterViewInit, OnChange } ngOnInit(): void { - let validators: __validation.IValidationHandler[] = []; + let validators: __validation.IObservableValidationHandler[] = []; if (this.validator) { validators = validators.concat(this.arrayUtility.arrayify(this.validator)); @@ -52,11 +52,10 @@ export class ValidationGroupComponent implements OnInit, AfterViewInit, OnChange validators = validators.concat(this.arrayUtility.arrayify(this.validators)); } - this.groupValidator.setValidators(validators); + this.groupValidator.initValidator(validators, this.validationControl.valueChanges, this.validationControl); } ngAfterViewInit(): void { - this.groupValidator.afterInit(this.validationControl); this.validationControl.updateValueAndValidity(this.model || undefined); } diff --git a/source/componentsDowngrade.ts b/source/componentsDowngrade.ts index a3266818..7e21fb68 100644 --- a/source/componentsDowngrade.ts +++ b/source/componentsDowngrade.ts @@ -12,6 +12,7 @@ import { ButtonAsyncComponent, ButtonLinkComponent, ButtonLongClickComponent, + ButtonRouteComponent, ButtonSubmitComponent, ButtonToggleComponent, } from './components/buttons/index'; @@ -49,7 +50,6 @@ export const documentServiceName: string = 'documentWrapper'; export const columnSearchFilterName: string = 'columnSearchFilter'; export const sorterServiceName: string = 'rlSorterService'; export const windowServiceName: string = 'windowWrapper'; -export const uiRouterServiceName: string = '$state'; const componentsDowngradeModule = angular.module(moduleName, []); @@ -61,8 +61,6 @@ export function PipeDowngrader(pipe: PipeTransform) { } export function downgradeComponentsToAngular1(upgradeAdapter: UpgradeAdapter) { - upgradeAdapter.upgradeNg1Provider(uiRouterServiceName); - componentsDowngradeModule.value(defaultThemeValueName, upgradeAdapter.downgradeNg2Provider('defaultThemeNg1')); componentsDowngradeModule.filter('isEmpty', PipeDowngrader(new IsEmptyPipe(services.object.objectUtility))); @@ -76,6 +74,7 @@ export function downgradeComponentsToAngular1(upgradeAdapter: UpgradeAdapter) { componentsDowngradeModule.directive('rlButtonAsyncNg', upgradeAdapter.downgradeNg2Component(ButtonAsyncComponent)); componentsDowngradeModule.directive('rlButtonLinkNg', upgradeAdapter.downgradeNg2Component(ButtonLinkComponent)); componentsDowngradeModule.directive('rlButtonLongClickNg', upgradeAdapter.downgradeNg2Component(ButtonLongClickComponent)); + componentsDowngradeModule.directive('rlButtonRouteNg', upgradeAdapter.downgradeNg2Component(ButtonRouteComponent)); componentsDowngradeModule.directive('rlButtonSubmitNg', upgradeAdapter.downgradeNg2Component(ButtonSubmitComponent)); componentsDowngradeModule.directive('rlButtonToggleNg', upgradeAdapter.downgradeNg2Component(ButtonToggleComponent)); componentsDowngradeModule.directive('rlCheckboxNg', upgradeAdapter.downgradeNg2Component(CheckboxComponent)); diff --git a/source/services/autosaveAction/autosaveAction.service.tests.ts b/source/services/autosaveAction/autosaveAction.service.tests.ts index 46b18dce..3f1acafb 100644 --- a/source/services/autosaveAction/autosaveAction.service.tests.ts +++ b/source/services/autosaveAction/autosaveAction.service.tests.ts @@ -1,3 +1,4 @@ +import { Subject } from 'rxjs'; import { rlFakeAsync, rlTick, flushMicrotasks, mock, IMockedRequest } from 'rl-async-testing'; import { services } from 'typescript-angular-utilities'; @@ -7,26 +8,33 @@ import { AsyncHelper } from '../async/async.service'; describe('AutosaveActionService', () => { let autosaveAction: AutosaveActionService; let mockAction: IMockedRequest; + let saving: boolean; + let complete: boolean; + let successful: boolean; beforeEach(() => { const digestMock = { runDigestCycle: sinon.spy(), }; - autosaveAction = new AutosaveActionService(new services.timeout.TimeoutService(), new AsyncHelper(), digestMock); + autosaveAction = new AutosaveActionService(new services.timeout.TimeoutService(), new AsyncHelper()); + + autosaveAction.saving$.subscribe(_saving => saving = _saving); + autosaveAction.complete$.subscribe(_complete => complete = _complete); + autosaveAction.successful$.subscribe(_successful => successful = _successful); mockAction = mock.request(); autosaveAction.trigger(mockAction()); - expect(autosaveAction.saving).to.be.true; + expect(saving).to.be.true; }); it('should set successful to true if the request resolves successfully', rlFakeAsync((): void => { mockAction.flush(); - expect(autosaveAction.saving).to.be.false; - expect(autosaveAction.complete).to.be.true; - expect(autosaveAction.successful).to.be.true; + expect(saving).to.be.false; + expect(complete).to.be.true; + expect(successful).to.be.true; rlTick(COMPLETE_MESSAGE_DURATION); flushMicrotasks(); @@ -37,9 +45,9 @@ describe('AutosaveActionService', () => { autosaveAction.trigger(mockAction()); mockAction.flush(); - expect(autosaveAction.saving).to.be.false; - expect(autosaveAction.complete).to.be.true; - expect(autosaveAction.successful).to.be.false; + expect(saving).to.be.false; + expect(complete).to.be.true; + expect(successful).to.be.false; rlTick(COMPLETE_MESSAGE_DURATION); flushMicrotasks(); @@ -48,11 +56,11 @@ describe('AutosaveActionService', () => { it('should set complete to false after the duration', rlFakeAsync((): void => { mockAction.flush(); - expect(autosaveAction.complete).to.be.true; + expect(complete).to.be.true; rlTick(COMPLETE_MESSAGE_DURATION); flushMicrotasks(); - expect(autosaveAction.complete).to.be.false; + expect(complete).to.be.false; })); }); diff --git a/source/services/autosaveAction/autosaveAction.service.ts b/source/services/autosaveAction/autosaveAction.service.ts index b0be536f..f26ba4f7 100644 --- a/source/services/autosaveAction/autosaveAction.service.ts +++ b/source/services/autosaveAction/autosaveAction.service.ts @@ -1,52 +1,52 @@ import { Injectable } from '@angular/core'; +import { Observable, BehaviorSubject } from 'rxjs'; import { services } from 'typescript-angular-utilities'; -import __timeout = services.timeout; -import __digest = services.digestService; +import TimeoutService = services.timeout.TimeoutService; import { AsyncHelper, IWaitValue } from '../async/async.service'; export const COMPLETE_MESSAGE_DURATION: number = 1000; export interface IAutosaveActionService { - trigger(promise: Promise): void; - saving: boolean; - complete: boolean; - successful: boolean; + trigger(waitOn: IWaitValue): void; + saving$: Observable; + complete$: Observable; + successful$: Observable; } @Injectable() export class AutosaveActionService implements IAutosaveActionService { - timeoutService: __timeout.TimeoutService; + timeoutService: TimeoutService; asyncService: AsyncHelper; - digestService: __digest.IDigestService; - constructor(timeoutService: __timeout.TimeoutService - , asyncService: AsyncHelper - , digestService: __digest.DigestService) { + constructor(timeoutService: TimeoutService + , asyncService: AsyncHelper) { this.timeoutService = timeoutService; this.asyncService = asyncService; - this.digestService = digestService; + this._saving$ = new BehaviorSubject(false); + this._complete$ = new BehaviorSubject(false); + this._successful$ = new BehaviorSubject(false); } - private _saving: boolean; - private _complete: boolean; - private _successful: boolean; + private _saving$: BehaviorSubject; + private _complete$: BehaviorSubject; + private _successful$: BehaviorSubject; - get saving(): boolean { - return this._saving; + get saving$(): Observable { + return this._saving$.asObservable(); } - get complete(): boolean { - return this._complete; + get complete$(): Observable { + return this._complete$.asObservable(); } - get successful(): boolean { - return this._successful; + get successful$(): Observable { + return this._successful$.asObservable(); } trigger(waitOn: IWaitValue): void { - this._saving = true; + this._saving$.next(true); this.asyncService.waitAsObservable(waitOn) .subscribe(this.autosaveSuccessful, this.autosaveFailed); } @@ -60,14 +60,10 @@ export class AutosaveActionService implements IAutosaveActionService { } private resolveAutosave = (success: boolean): void => { - this._saving = false; - this._complete = true; - this._successful = success; + this._saving$.next(false); + this._complete$.next(true); + this._successful$.next(success); - this.timeoutService.setTimeout(() => { - this._complete = false; - // remove this once ng1 goes away - this.digestService.runDigestCycle(); - }, COMPLETE_MESSAGE_DURATION); + this.timeoutService.setTimeout(() => this._complete$.next(false), COMPLETE_MESSAGE_DURATION); } } diff --git a/source/services/componentValidator/componentValidator.service.tests.ts b/source/services/componentValidator/componentValidator.service.tests.ts index ff077a50..c6ff666d 100644 --- a/source/services/componentValidator/componentValidator.service.tests.ts +++ b/source/services/componentValidator/componentValidator.service.tests.ts @@ -1,14 +1,13 @@ -import { Subject } from 'rxjs'; +import { Subject, Observable } from 'rxjs'; import { services } from 'typescript-angular-utilities'; import __validation = services.validation; import { ComponentValidator } from './componentValidator.service'; interface IControlMock { - statusChanges?: Subject; + valueChanges?: Subject; errors?: any; rlErrorMessage?: string; - value?: any; } describe('ComponentValidator', () => { @@ -18,71 +17,53 @@ describe('ComponentValidator', () => { componentValidator = new ComponentValidator(new __validation.ValidationService({})); }); - it('should register the validators', (): void => { + it('should register the validators and set the value stream', (): void => { const registerSpy = sinon.spy(); componentValidator.validator.registerValidationHandler = registerSpy; const validators: any[] = [{}, {}]; + const value$ = new Subject(); - componentValidator.setValidators(validators); + componentValidator.initValidator(validators, value$, {}); sinon.assert.calledTwice(registerSpy); sinon.assert.calledWith(registerSpy, validators[0]); sinon.assert.calledWith(registerSpy, validators[1]); + expect(componentValidator.value$).to.equal(value$); }); - it('should subscribe to status changes on the control', (): void => { - const setErrorSpy = sinon.spy(); - componentValidator.setError = setErrorSpy; - const control: IControlMock = { statusChanges: new Subject() }; + it('should subscribe to the error stream and set rlErrorMessage on the control', (): void => { + const control: any = {}; + const validator = { validate: () => Observable.of('error') }; + const value$ = new Subject(); - componentValidator.afterInit(control); + componentValidator.initValidator([validator], value$, control); - sinon.assert.calledOnce(setErrorSpy); - sinon.assert.calledWith(setErrorSpy, control); - setErrorSpy.reset(); - - control.statusChanges.next(null); - - sinon.assert.calledOnce(setErrorSpy); - sinon.assert.calledWith(setErrorSpy, control); + expect(control.rlErrorMessage).to.equal('error'); }); it('should return null if validation passes', (): void => { - const validateSpy = sinon.spy(() => true); - componentValidator.validator.validate = validateSpy; - const control: IControlMock = { value: 3 }; + const validateStream = new Subject(); + componentValidator.validator.validate = sinon.spy(() => validateStream); + const control: IControlMock = { valueChanges: new Subject() }; + let result; + + componentValidator.validate(control).subscribe(error => result = error); - const result = componentValidator.validate(control); + validateStream.next(null); - sinon.assert.calledOnce(validateSpy); - sinon.assert.calledWith(validateSpy, 3); expect(result).to.be.null; }); it('should return the error if validation fails', (): void => { - const validateSpy = sinon.spy(() => false); - componentValidator.validator.validate = validateSpy; - const control: IControlMock = { value: 3 }; - componentValidator.error = 'error'; - componentValidator.errorType = 'errorType'; + const validateStream = new Subject(); + componentValidator.validator.validate = sinon.spy(() => validateStream); + const control: IControlMock = { valueChanges: new Subject() }; + let result; - const result = componentValidator.validate(control); + componentValidator.validate(control).subscribe(error => result = error); - sinon.assert.calledOnce(validateSpy); - sinon.assert.calledWith(validateSpy, 3); - expect(result['errorType']).to.equal('error'); - }); - - it('should set rlErrorMessage on the control to the first error', (): void => { - const control: IControlMock = { - errors: { - myError: 'error', - otherError: 'other', - }, - }; + validateStream.next('error'); - componentValidator.setError(control); - - expect(control.rlErrorMessage).to.equal('error'); + expect(result).to.deep.equal({ validationError: 'error' }); }); }); diff --git a/source/services/componentValidator/componentValidator.service.ts b/source/services/componentValidator/componentValidator.service.ts index 7ec69cb5..e147058f 100644 --- a/source/services/componentValidator/componentValidator.service.ts +++ b/source/services/componentValidator/componentValidator.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core'; import { FormControl } from '@angular/forms'; +import { Observable } from 'rxjs'; import { first, values, each } from 'lodash'; import { services } from 'typescript-angular-utilities'; @@ -9,48 +10,32 @@ import { IControlValidator } from '../../types/formValidators'; @Injectable() export class ComponentValidator { - validator: __validation.ISimpleValidator; - error: string; - errorType: string; + validator: __validation.ObservableValidator; + value$: Observable; - validationService: __validation.IValidationService; constructor(validationService: __validation.ValidationService) { - this.validationService = validationService; - this.validator = this.validationService.buildCustomValidator((error: string, name: string): void => { - this.error = error; - this.errorType = name || 'customValidation'; - }); + this.validator = validationService.buildObservableValidator(); } - setValidators(validators: __validation.IValidationHandler[]): void { - each(validators, (customValidator: __validation.IValidationHandler): void => { + initValidator(validators: __validation.IObservableValidationHandler[], value$: Observable, control: IControlValidator): void { + each(validators, (customValidator: __validation.IObservableValidationHandler): void => { this.validator.registerValidationHandler(customValidator); }); + this.value$ = value$; + this.error$.subscribe(error => control.rlErrorMessage = error); } - afterInit(control: FormControl): void { - control.statusChanges.subscribe((value: any): void => { - this.setError(control); - }); - this.setError(control); + get error$(): Observable { + return this.validator.validate(this.value$); } - validate(control: FormControl): any { - if (this.validator.validate(control.value)) { + validate(control: FormControl): Observable { + return this.validator.validate(control.valueChanges).map(validation => { + if (validation) { + return { validationError: validation }; + } return null; - } - let errors: any = {}; - errors[this.errorType] = this.error; - return errors; - } - - setError(control: IControlValidator): string { - if (!control) { - return; - } - - this.error = first(values(control.errors)); - control.rlErrorMessage = this.error; + }); } } diff --git a/source/ui.module.ts b/source/ui.module.ts index f1041f70..e14caa25 100644 --- a/source/ui.module.ts +++ b/source/ui.module.ts @@ -1,5 +1,6 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; import { ReactiveFormsModule } from '@angular/forms'; import { BEHAVIOR_DIRECTIVES } from './behaviors/index'; @@ -12,7 +13,8 @@ import { FormComponent } from'./components/form/form'; import { INPUT_DIRECTIVES } from'./components/inputs/index'; import { MultiStepIndicatorComponent } from'./components/multiStepIndicator/multiStepIndicator'; import { RatingBarComponent } from'./components/ratingBar/ratingBar'; -import { SIMPLE_CARD_DIRECTIVES } from'./components/simpleCardList/index'; +import { SIMPLE_CARD_DIRECTIVES } from './components/simpleCardList/index'; +import { StepComponent } from './components/multiStepIndicator/step.component'; import { StringWithWatermarkComponent } from'./components/stringWithWatermark/stringWithWatermark'; import { TABS_COMPONENT } from'./components/tabs/index'; import { ValidationGroupComponent } from'./components/validationGroup/validationGroup'; @@ -42,6 +44,7 @@ export const componentsList: any[] = [ MultiStepIndicatorComponent, RatingBarComponent, SIMPLE_CARD_DIRECTIVES, + StepComponent, StringWithWatermarkComponent, TABS_COMPONENT, ValidationGroupComponent, @@ -60,6 +63,7 @@ export * from './componentProviders.module'; imports: [ CommonModule, ReactiveFormsModule, + RouterModule, ], declarations: [ ...componentsList, diff --git a/system.config.js b/system.config.js index cadebcbf..49c7283e 100644 --- a/system.config.js +++ b/system.config.js @@ -6,7 +6,6 @@ const map = { 'angular-mocks': 'node_modules/angular-mocks/angular-mocks', 'angular-animate': 'node_modules/angular-animate/angular-animate.js', 'angular-ui-bootstrap': 'node_modules/angular-ui-bootstrap/index.js', - 'angular-ui-router': 'node_modules/angular-ui-router/release/angular-ui-router.min.js', 'angular-sanitize': 'node_modules/angular-sanitize/index.js', 'angular2-uuid': 'node_modules/angular2-uuid', 'bootstrap': 'node_modules/bootstrap/dist/js/bootstrap.js', @@ -62,6 +61,9 @@ var packages = { 'node_modules': { defaultExtension: 'js', }, + '@angular/router': { + main: 'index.js', + }, 'angular2-uuid': { main: 'index.js', }, From fbdeee9a5d2a39d38b50b22a13d10c11f1f0586b Mon Sep 17 00:00:00 2001 From: theoriginaljosh Date: Fri, 28 Oct 2016 14:00:34 -0400 Subject: [PATCH 5/9] fixing error in angular 1 component --- source/components/inputs/textbox/textbox.ng1.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/components/inputs/textbox/textbox.ng1.html b/source/components/inputs/textbox/textbox.ng1.html index f594a1c6..ea6ac2ea 100644 --- a/source/components/inputs/textbox/textbox.ng1.html +++ b/source/components/inputs/textbox/textbox.ng1.html @@ -1,4 +1,4 @@ -
    +
    {{input.inputValidator.error}} From 327e27d0dd5bbb290b528a2ceb58e6bc634336a1 Mon Sep 17 00:00:00 2001 From: theoriginaljosh Date: Fri, 28 Oct 2016 14:01:16 -0400 Subject: [PATCH 6/9] setting @types/moment-timezone to only use version 0.2.31 if you allow minor updated .32 will cause build errors. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0537cb4f..23b66dad 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "@types/jquery": "^2.0.32", "@types/jquery.jsignature": "^2.0.28", "@types/lodash": "^4.14.36", - "@types/moment-timezone": "^0.2.31", + "@types/moment-timezone": "0.2.31", "@types/sinon": "^1.16.31", "angular": "~1.5.3", "angular-animate": "~1.5.3", From 55c64cbba07725659d7622b59d3fa09345d05b7a Mon Sep 17 00:00:00 2001 From: theoriginaljosh Date: Fri, 28 Oct 2016 14:06:13 -0400 Subject: [PATCH 7/9] adding warning css class added to absoluteTime, dateTime, select, spinner, textarea, typeahead --- source/components/inputs/absoluteTime/absoluteTime.html | 1 + source/components/inputs/dateTime/dateTime.html | 1 + source/components/inputs/dateTime/dateTime.ng1.html | 2 +- source/components/inputs/select/select.html | 1 + source/components/inputs/select/select.ng1.html | 2 +- source/components/inputs/spinner/spinner.html | 1 + source/components/inputs/spinner/spinner.ng1.html | 2 +- source/components/inputs/textarea/textarea.html | 1 + source/components/inputs/textarea/textarea.ng1.html | 2 +- source/components/inputs/typeahead/typeahead.html | 1 + source/components/inputs/typeahead/typeahead.ng1.html | 2 +- 11 files changed, 11 insertions(+), 5 deletions(-) diff --git a/source/components/inputs/absoluteTime/absoluteTime.html b/source/components/inputs/absoluteTime/absoluteTime.html index db1ec314..57eb57d7 100644 --- a/source/components/inputs/absoluteTime/absoluteTime.html +++ b/source/components/inputs/absoluteTime/absoluteTime.html @@ -1,4 +1,5 @@
    diff --git a/source/components/inputs/dateTime/dateTime.html b/source/components/inputs/dateTime/dateTime.html index 49943f7b..3d0fa263 100644 --- a/source/components/inputs/dateTime/dateTime.html +++ b/source/components/inputs/dateTime/dateTime.html @@ -1,4 +1,5 @@
    diff --git a/source/components/inputs/dateTime/dateTime.ng1.html b/source/components/inputs/dateTime/dateTime.ng1.html index efa85948..1219248c 100644 --- a/source/components/inputs/dateTime/dateTime.ng1.html +++ b/source/components/inputs/dateTime/dateTime.ng1.html @@ -1,4 +1,4 @@ -
    +
    diff --git a/source/components/inputs/select/select.html b/source/components/inputs/select/select.html index 202a785e..c3836c9f 100644 --- a/source/components/inputs/select/select.html +++ b/source/components/inputs/select/select.html @@ -1,4 +1,5 @@
    diff --git a/source/components/inputs/select/select.ng1.html b/source/components/inputs/select/select.ng1.html index d39f10f3..f3d920bf 100644 --- a/source/components/inputs/select/select.ng1.html +++ b/source/components/inputs/select/select.ng1.html @@ -1,4 +1,4 @@ -
    +
    diff --git a/source/components/inputs/spinner/spinner.html b/source/components/inputs/spinner/spinner.html index f5133a1f..c742d7e9 100644 --- a/source/components/inputs/spinner/spinner.html +++ b/source/components/inputs/spinner/spinner.html @@ -1,6 +1,7 @@