#3527 feature - Added common components like i18n and local storage
11 files added
8 files modified
| .. | .. |
|---|
| 1 | +// Place your settings in this file to overwrite default and user settings. |
|---|
| 2 | +{ |
|---|
| 3 | + "typescript.tsdk": "./node_modules/typescript/lib" |
|---|
| 4 | +} |
|---|
| .. | .. |
|---|
| 1 | 1 | { |
|---|
| 2 | | - "name": "angular-quickstart", |
|---|
| 3 | | - "version": "1.0.0", |
|---|
| 2 | + "name": "securis", |
|---|
| 3 | + "version": "2.0.0", |
|---|
| 4 | 4 | "description": "QuickStart package.json from the documentation, supplemented with testing support", |
|---|
| 5 | 5 | "scripts": { |
|---|
| 6 | 6 | "build": "tsc -p src/", |
|---|
| .. | .. |
|---|
| 36 | 36 | "@covalent/core": "^1.0.0-beta.2", |
|---|
| 37 | 37 | "@covalent/dynamic-forms": "^1.0.0-beta.2", |
|---|
| 38 | 38 | "@covalent/http": "^1.0.0-beta.2", |
|---|
| 39 | + "angular-2-local-storage": "^1.0.1", |
|---|
| 39 | 40 | "angular-in-memory-web-api": "~0.2.4", |
|---|
| 40 | 41 | "core-js": "^2.4.1", |
|---|
| 41 | 42 | "hammerjs": "^2.0.8", |
|---|
| 43 | + "ng2-toastr": "^1.5.1", |
|---|
| 42 | 44 | "rxjs": "^5.0.1", |
|---|
| 43 | 45 | "systemjs": "0.19.40", |
|---|
| 44 | 46 | "zone.js": "^0.7.4" |
|---|
| 45 | 47 | }, |
|---|
| 46 | 48 | "devDependencies": { |
|---|
| 47 | | - "concurrently": "^3.2.0", |
|---|
| 48 | | - "lite-server": "^2.2.2", |
|---|
| 49 | | - "typescript": "~2.0.10", |
|---|
| 49 | + "@types/jasmine": "2.5.36", |
|---|
| 50 | + "@types/node": "^6.0.46", |
|---|
| 50 | 51 | "canonical-path": "0.0.2", |
|---|
| 51 | | - "tslint": "^3.15.1", |
|---|
| 52 | | - "lodash": "^4.16.4", |
|---|
| 52 | + "concurrently": "^3.2.0", |
|---|
| 53 | 53 | "jasmine-core": "~2.4.1", |
|---|
| 54 | 54 | "karma": "^1.3.0", |
|---|
| 55 | 55 | "karma-chrome-launcher": "^2.0.0", |
|---|
| 56 | 56 | "karma-cli": "^1.0.1", |
|---|
| 57 | 57 | "karma-jasmine": "^1.0.2", |
|---|
| 58 | 58 | "karma-jasmine-html-reporter": "^0.2.2", |
|---|
| 59 | + "lite-server": "^2.2.2", |
|---|
| 60 | + "lodash": "^4.16.4", |
|---|
| 59 | 61 | "protractor": "~4.0.14", |
|---|
| 60 | 62 | "rimraf": "^2.5.4", |
|---|
| 61 | | - "@types/node": "^6.0.46", |
|---|
| 62 | | - "@types/jasmine": "2.5.36" |
|---|
| 63 | + "tslint": "^3.15.1", |
|---|
| 64 | + "typescript": "^2.2.1" |
|---|
| 63 | 65 | }, |
|---|
| 64 | 66 | "repository": {} |
|---|
| 65 | 67 | } |
|---|
| .. | .. |
|---|
| 1 | | -import { Component } from '@angular/core'; |
|---|
| 1 | +import { Component, AfterViewInit } from '@angular/core'; |
|---|
| 2 | 2 | import { DomSanitizer } from '@angular/platform-browser'; |
|---|
| 3 | 3 | import { MdIconRegistry } from '@angular/material'; |
|---|
| 4 | +import { UserService } from './user.service'; |
|---|
| 5 | +import { LocalStorageService } from 'angular-2-local-storage'; |
|---|
| 6 | +import { TdMediaService } from '@covalent/core'; |
|---|
| 7 | +import { Router } from '@angular/router'; |
|---|
| 4 | 8 | |
|---|
| 5 | 9 | // https://github.com/Teradata/covalent-quickstart/tree/develop/src/app |
|---|
| 6 | 10 | // https://teradata.github.io/covalent-quickstart/#/ |
|---|
| .. | .. |
|---|
| 11 | 15 | }) |
|---|
| 12 | 16 | |
|---|
| 13 | 17 | |
|---|
| 14 | | -export class AppComponent { |
|---|
| 18 | +export class AppComponent implements AfterViewInit { |
|---|
| 15 | 19 | |
|---|
| 16 | | - constructor(private _iconRegistry: MdIconRegistry, |
|---|
| 17 | | - private _domSanitizer: DomSanitizer) { |
|---|
| 18 | | - |
|---|
| 20 | + constructor(private userService: UserService, |
|---|
| 21 | + private router: Router, |
|---|
| 22 | + private media: TdMediaService, |
|---|
| 23 | + private _iconRegistry: MdIconRegistry, |
|---|
| 24 | + private _domSanitizer: DomSanitizer, |
|---|
| 25 | + private store: LocalStorageService) { |
|---|
| 26 | + this.registerIcons(); |
|---|
| 27 | + } |
|---|
| 28 | + |
|---|
| 29 | + private registerIcons() : void { |
|---|
| 19 | 30 | this._iconRegistry.addSvgIconInNamespace('assets', 'covalent', |
|---|
| 20 | 31 | this._domSanitizer.bypassSecurityTrustResourceUrl('https://raw.githubusercontent.com/Teradata/covalent-quickstart/develop/src/assets/icons/covalent.svg')); |
|---|
| 21 | 32 | this._iconRegistry.addSvgIconInNamespace('assets', 'teradata', |
|---|
| .. | .. |
|---|
| 36 | 47 | this._domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/querygrid.svg')); |
|---|
| 37 | 48 | } |
|---|
| 38 | 49 | |
|---|
| 50 | + ngAfterViewInit(): void { |
|---|
| 51 | + this.media.broadcast(); |
|---|
| 52 | + this.userService.isLoggedIn().subscribe(authOk => { |
|---|
| 53 | + this.router.navigateByUrl(authOk ? 'packs' : 'login'); |
|---|
| 54 | + }, |
|---|
| 55 | + err => /* Show message */ this.router.navigateByUrl('login')); |
|---|
| 56 | + } |
|---|
| 39 | 57 | } |
|---|
| .. | .. |
|---|
| 7 | 7 | import {CovalentHttpModule} from '@covalent/http'; |
|---|
| 8 | 8 | import {CovalentDynamicFormsModule} from '@covalent/dynamic-forms'; |
|---|
| 9 | 9 | |
|---|
| 10 | +import { LocalStorageModule } from 'angular-2-local-storage'; |
|---|
| 11 | +import { ToastModule } from 'ng2-toastr/ng2-toastr'; |
|---|
| 12 | + |
|---|
| 10 | 13 | import { AppComponent } from './app.component'; |
|---|
| 14 | +import { UserService } from './user.service'; |
|---|
| 11 | 15 | import { PackListComponent } from './pack.list.component'; |
|---|
| 12 | 16 | import { HeroDetailComponent } from './detail.component'; |
|---|
| 17 | +import { LoginFormComponent } from './login.form.component'; |
|---|
| 13 | 18 | |
|---|
| 14 | 19 | import { appRoutes, appRoutingProviders } from './app.routes'; |
|---|
| 20 | +import { requestOptionsProvider } from './common/default.requests.options'; |
|---|
| 21 | +import { LocaleServiceModule } from './common/i18n'; |
|---|
| 15 | 22 | |
|---|
| 16 | 23 | @NgModule({ |
|---|
| 17 | 24 | imports: [ |
|---|
| 25 | + LocalStorageModule.withConfig({ |
|---|
| 26 | + prefix: 'securis', |
|---|
| 27 | + storageType: 'localStorage' |
|---|
| 28 | + }), |
|---|
| 18 | 29 | BrowserModule, |
|---|
| 19 | 30 | FormsModule, |
|---|
| 20 | | - MaterialModule.forRoot(), |
|---|
| 31 | + MaterialModule, |
|---|
| 21 | 32 | CovalentCoreModule.forRoot(), |
|---|
| 22 | 33 | CovalentHttpModule.forRoot(), |
|---|
| 23 | 34 | CovalentDynamicFormsModule.forRoot(), |
|---|
| 35 | + ToastModule.forRoot(), |
|---|
| 36 | + LocaleServiceModule, |
|---|
| 24 | 37 | appRoutes, |
|---|
| 25 | 38 | ], |
|---|
| 26 | 39 | declarations: [ |
|---|
| 27 | 40 | HeroDetailComponent, |
|---|
| 28 | 41 | PackListComponent, |
|---|
| 42 | + LoginFormComponent, |
|---|
| 29 | 43 | AppComponent |
|---|
| 30 | 44 | ], |
|---|
| 31 | 45 | bootstrap: [ AppComponent ], |
|---|
| 32 | 46 | providers: [ |
|---|
| 47 | + UserService, |
|---|
| 33 | 48 | appRoutingProviders, |
|---|
| 49 | + requestOptionsProvider, |
|---|
| 34 | 50 | ] |
|---|
| 35 | 51 | }) |
|---|
| 36 | 52 | |
|---|
| .. | .. |
|---|
| 2 | 2 | |
|---|
| 3 | 3 | import { AppComponent } from './app.component'; |
|---|
| 4 | 4 | import { PackListComponent } from './pack.list.component'; |
|---|
| 5 | +import { LoginFormComponent } from './login.form.component'; |
|---|
| 5 | 6 | |
|---|
| 6 | 7 | const routes: Routes = [ |
|---|
| 7 | | - {path: '', redirectTo: '/packs', pathMatch: 'full'}, |
|---|
| 8 | + // {path: '', redirectTo: '/packs', pathMatch: 'full'}, |
|---|
| 8 | 9 | {path: 'packs', component: PackListComponent }, |
|---|
| 10 | + {path: 'login', component: LoginFormComponent } |
|---|
| 9 | 11 | ]; |
|---|
| 10 | 12 | /* {path: 'product', component: DashboardProductComponent, children: [ |
|---|
| 11 | 13 | {path: '', component: ProductOverviewComponent}, |
|---|
| .. | .. |
|---|
| 1 | +import { LocalStorageService } from 'angular-2-local-storage'; |
|---|
| 2 | +import { Injectable } from '@angular/core'; |
|---|
| 3 | +import { BaseRequestOptions, RequestOptions, Request, XHRBackend, XHRConnection} from '@angular/http'; |
|---|
| 4 | + |
|---|
| 5 | + |
|---|
| 6 | +// TODO: Chnage this to use Covalent Http helper service |
|---|
| 7 | +// https://www.npmjs.com/package/@covalent/http |
|---|
| 8 | + |
|---|
| 9 | +@Injectable() |
|---|
| 10 | +export class DefaultRequestOptions extends BaseRequestOptions { |
|---|
| 11 | + |
|---|
| 12 | + constructor(private store: LocalStorageService) { |
|---|
| 13 | + super(); |
|---|
| 14 | + |
|---|
| 15 | + // Set the default 'Content-Type' header |
|---|
| 16 | + this.headers.set('Content-Type', 'application/json'); |
|---|
| 17 | + let token = this.store.get<string>('token'); |
|---|
| 18 | + if (token) { |
|---|
| 19 | + this.headers.set('X-SECURIS-TOKEN', token); |
|---|
| 20 | + } |
|---|
| 21 | + |
|---|
| 22 | + } |
|---|
| 23 | +} |
|---|
| 24 | + |
|---|
| 25 | +@Injectable() |
|---|
| 26 | +export class ApiXHRBackend extends XHRBackend { |
|---|
| 27 | + createConnection(request: Request): XHRConnection { |
|---|
| 28 | + if (request.url.startsWith('/')){ |
|---|
| 29 | + // request.url = '/securis' + request.url; // prefix base url |
|---|
| 30 | + } |
|---|
| 31 | + return super.createConnection(request); |
|---|
| 32 | + } |
|---|
| 33 | +} |
|---|
| 34 | + |
|---|
| 35 | +export const requestOptionsProvider = { provide: RequestOptions, useClass: DefaultRequestOptions }; |
|---|
| 36 | + |
|---|
| 37 | +export const requestBackendProvider = { provide: XHRBackend, useClass: ApiXHRBackend }; |
|---|
| .. | .. |
|---|
| 1 | +import { Http } from '@angular/http'; |
|---|
| 2 | +import { ModuleWithProviders, NgModule, Inject, Injectable, Directive, ElementRef, HostListener, Input, Renderer } from '@angular/core'; |
|---|
| 3 | +declare var navigator:any; |
|---|
| 4 | + |
|---|
| 5 | +// Use as reference: https://github.com/ngx-translate/core/tree/master/src |
|---|
| 6 | +@Injectable() |
|---|
| 7 | +export class LocaleService { |
|---|
| 8 | + get URL_TPL() {return 'src/lang/messages-{0}.json'}; |
|---|
| 9 | + |
|---|
| 10 | + private _currentLang : string = null; |
|---|
| 11 | + private _messages : any = null; |
|---|
| 12 | + private _elements = new Array<ElementRef>(); |
|---|
| 13 | + private constructor(private http: Http, @Inject('INITIAL_LANG') initLang: string) { |
|---|
| 14 | + this._currentLang = initLang || this.getBrowserLang(); |
|---|
| 15 | + } |
|---|
| 16 | + |
|---|
| 17 | + get lang() : string { |
|---|
| 18 | + return this._currentLang; |
|---|
| 19 | + } |
|---|
| 20 | + |
|---|
| 21 | + set lang(newLang: string) { |
|---|
| 22 | + this._currentLang = newLang; |
|---|
| 23 | + this.http.get(this._format(this.URL_TPL, newLang)).subscribe((data) => { |
|---|
| 24 | + this._messages = data; |
|---|
| 25 | + this.reloadTexts(); |
|---|
| 26 | + }); |
|---|
| 27 | + } |
|---|
| 28 | + |
|---|
| 29 | + isLoaded() : boolean { |
|---|
| 30 | + return !!this._messages |
|---|
| 31 | + } |
|---|
| 32 | + |
|---|
| 33 | + getBrowserLang() : string { |
|---|
| 34 | + var l; |
|---|
| 35 | + if (!navigator) return 'en'; |
|---|
| 36 | + |
|---|
| 37 | + if (navigator.languages && navigator.languages.length) { |
|---|
| 38 | + l = navigator.languages[0]; |
|---|
| 39 | + } else { |
|---|
| 40 | + l = navigator.language || 'en'; |
|---|
| 41 | + } |
|---|
| 42 | + l = l.replace(/-.*/gi, ''); |
|---|
| 43 | + if (l !== 'en' && l !== 'es') |
|---|
| 44 | + return 'en'; |
|---|
| 45 | + return l; |
|---|
| 46 | + } |
|---|
| 47 | + |
|---|
| 48 | + /** |
|---|
| 49 | + * It works similar to MessageFormat in Java |
|---|
| 50 | + */ |
|---|
| 51 | + _format(str: string, ...params: Array<string>) { |
|---|
| 52 | + |
|---|
| 53 | + return str.replace(/\{(\d+)\}/g, function(match, index) { |
|---|
| 54 | + return params[index]; |
|---|
| 55 | + }); |
|---|
| 56 | + }; |
|---|
| 57 | + |
|---|
| 58 | + reloadTexts() : void { |
|---|
| 59 | + this._elements.forEach((ele: ElementRef) => { |
|---|
| 60 | + |
|---|
| 61 | + var txt = ele.nativeElement.getAttribute('i18n'); |
|---|
| 62 | + if (!!txt) { |
|---|
| 63 | + ele.nativeElement.textContent = this.get(txt); |
|---|
| 64 | + } |
|---|
| 65 | + }) |
|---|
| 66 | + } |
|---|
| 67 | + |
|---|
| 68 | + add(ele: ElementRef) { |
|---|
| 69 | + this._elements.push(ele); |
|---|
| 70 | + } |
|---|
| 71 | + |
|---|
| 72 | + /** |
|---|
| 73 | + * It accepts direct messages and templates: |
|---|
| 74 | + * { |
|---|
| 75 | + * "hello": "hola", |
|---|
| 76 | + * "Hello {0}!!: "Hola {0}!!" |
|---|
| 77 | + * } |
|---|
| 78 | + * $L.get('hello'); // This returns "hola" |
|---|
| 79 | + * $L.get('Hello {0}!!', 'John'); // This returns: "Hola John!!" if language is spanish |
|---|
| 80 | + */ |
|---|
| 81 | + get(msg: string) : string { |
|---|
| 82 | + msg = msg.trim(); |
|---|
| 83 | + var trans_msg = msg; |
|---|
| 84 | + |
|---|
| 85 | + if (this.isLoaded()) { |
|---|
| 86 | + if (this._messages[msg]) { |
|---|
| 87 | + trans_msg = this._messages[msg]; |
|---|
| 88 | + } else if (this._messages[msg.toLowerCase()]) { |
|---|
| 89 | + trans_msg = this._messages[msg.toLowerCase()]; |
|---|
| 90 | + } else { |
|---|
| 91 | + this._currentLang !== 'es' && console.error("Missing i18 key: " + msg); |
|---|
| 92 | + trans_msg = msg; |
|---|
| 93 | + } |
|---|
| 94 | + } |
|---|
| 95 | + // Enviar evento cuando el idioma cambia al $rootScope |
|---|
| 96 | + |
|---|
| 97 | + if (arguments.length === 1) return trans_msg; |
|---|
| 98 | + var params = Array.prototype.slice.call(arguments, 1); |
|---|
| 99 | + return this._format.apply(trans_msg, params); |
|---|
| 100 | + } |
|---|
| 101 | + |
|---|
| 102 | +} |
|---|
| 103 | + |
|---|
| 104 | + |
|---|
| 105 | +@Directive({ selector: '[i18n]' }) |
|---|
| 106 | +export class I18nDirective { |
|---|
| 107 | + constructor(private el: ElementRef, private renderer: Renderer, private $L: LocaleService) { |
|---|
| 108 | + } |
|---|
| 109 | + |
|---|
| 110 | + ngAfterViewChecked() { |
|---|
| 111 | + var txt = this.el.nativeElement.getAttribute('i18n') || this.el.nativeElement.textContent; |
|---|
| 112 | + this.renderer.setElementProperty(this.el.nativeElement, 'i18n', txt.trim()); |
|---|
| 113 | + this.$L.add(this.el); |
|---|
| 114 | + |
|---|
| 115 | + this.renderer.setElementProperty(this.el.nativeElement, 'innerHTML', this.$L.get(txt)); |
|---|
| 116 | + } |
|---|
| 117 | +} |
|---|
| 118 | + |
|---|
| 119 | +@NgModule({ |
|---|
| 120 | + providers: [ <any>LocaleService ] |
|---|
| 121 | +}) |
|---|
| 122 | +export class LocaleServiceModule { |
|---|
| 123 | + static withConfig(initLang?: string): ModuleWithProviders { |
|---|
| 124 | + return { |
|---|
| 125 | + ngModule: LocaleServiceModule, |
|---|
| 126 | + providers: [ |
|---|
| 127 | + { provide: 'INITIAL_LANG', useValue: initLang } |
|---|
| 128 | + ] |
|---|
| 129 | + } |
|---|
| 130 | + } |
|---|
| 131 | +} |
|---|
| 132 | + |
|---|
| 133 | + |
|---|
| .. | .. |
|---|
| 1 | +import { Http } from '@angular/http'; |
|---|
| 2 | +import { Router } from '@angular/router'; |
|---|
| 3 | +import { AfterViewInit, Component, Input } from '@angular/core'; |
|---|
| 4 | +import { UserService } from './user.service'; |
|---|
| 5 | +import { ToastsManager } from 'ng2-toastr/ng2-toastr'; |
|---|
| 6 | + |
|---|
| 7 | +class LoginData { |
|---|
| 8 | + username: string; |
|---|
| 9 | + password: string; |
|---|
| 10 | +} |
|---|
| 11 | + |
|---|
| 12 | +@Component({ |
|---|
| 13 | + selector: 'login-form', |
|---|
| 14 | + templateUrl: "src/app/login.form.html" |
|---|
| 15 | +}) |
|---|
| 16 | +export class LoginFormComponent implements AfterViewInit { |
|---|
| 17 | + data = new LoginData(); |
|---|
| 18 | + |
|---|
| 19 | + public constructor(private toaster: ToastsManager, |
|---|
| 20 | + private router: Router, |
|---|
| 21 | + private userService: UserService) { |
|---|
| 22 | + } |
|---|
| 23 | + |
|---|
| 24 | + public login() { |
|---|
| 25 | + this.userService.login(this.data.username, this.data.password).subscribe( |
|---|
| 26 | + token => this.toaster.info('Hola'), |
|---|
| 27 | + err => this.toaster.error('Hubo un error: ' + err)); |
|---|
| 28 | + } |
|---|
| 29 | + |
|---|
| 30 | + public clear() { |
|---|
| 31 | + this.data.username = ''; |
|---|
| 32 | + this.data.password = ''; |
|---|
| 33 | + } |
|---|
| 34 | + |
|---|
| 35 | + ngAfterViewInit() { |
|---|
| 36 | + |
|---|
| 37 | + } |
|---|
| 38 | +} |
|---|
| .. | .. |
|---|
| 1 | +<md-card> |
|---|
| 2 | + <md-card-title layout="row" layout-align="start end"><md-icon class="md-icon-logo" svgSrc="assets/icons/logo.svg"></md-icon> <span class="md-app-title" i18n> |
|---|
| 3 | + SeCuris Login</span></md-card-title> |
|---|
| 4 | + <md-card-subtitle>Sign in via your current SeCuris account</md-card-subtitle> |
|---|
| 5 | + <md-divider></md-divider> |
|---|
| 6 | + <md-card-content> |
|---|
| 7 | + <form #loginForm="ngForm" class="inset"> |
|---|
| 8 | + <div layout="row"> |
|---|
| 9 | + <md-input-container> |
|---|
| 10 | + <input mdInput flex placeholder="Username" type="text" [(ngModel)]="data.username" name="username" required /> |
|---|
| 11 | + </md-input-container> |
|---|
| 12 | + </div> |
|---|
| 13 | + <div layout="row"> |
|---|
| 14 | + <md-input-container> |
|---|
| 15 | + <input mdInput (keyup.enter)="loginForm.form.valid && login()" flex placeholder="Password" type="password" [(ngModel)]="data.password" name="password" required/> |
|---|
| 16 | + </md-input-container> |
|---|
| 17 | + </div> |
|---|
| 18 | + </form> |
|---|
| 19 | + <div id="invalid-auth-msg" *ngIf="invalidError" class="tc-red-600 text-center" flex i18n>The username or password is incorrect. Please try again.</div> |
|---|
| 20 | + </md-card-content> |
|---|
| 21 | + <md-divider></md-divider> |
|---|
| 22 | + <md-card-actions> |
|---|
| 23 | + <button flex [disabled]="!loginForm.form.valid" md-raised-button color="primary" (click)="login()">Sign In</button> |
|---|
| 24 | + </md-card-actions> |
|---|
| 25 | +</md-card> |
|---|
| .. | .. |
|---|
| 1 | +import { Hero } from './hero'; |
|---|
| 1 | 2 | import { Component, AfterViewInit } from '@angular/core'; |
|---|
| 2 | 3 | import { TdMediaService } from '@covalent/core'; |
|---|
| 3 | 4 | |
|---|
| .. | .. |
|---|
| 1 | +import { Injectable } from '@angular/core'; |
|---|
| 2 | +import { Router } from '@angular/router'; |
|---|
| 3 | +import { Location } from '@angular/common'; |
|---|
| 4 | +import { Http, RequestOptions, Response, Headers } from '@angular/http'; |
|---|
| 5 | +import { Observable } from 'rxjs/Observable'; |
|---|
| 6 | + |
|---|
| 7 | +import { LocalStorageService } from 'angular-2-local-storage'; |
|---|
| 8 | + |
|---|
| 9 | +const SECURIS_TOKEN = "X-SECURIS-TOKEN"; |
|---|
| 10 | + |
|---|
| 11 | +@Injectable() |
|---|
| 12 | +export class UserService { |
|---|
| 13 | + |
|---|
| 14 | + constructor(private router: Router, |
|---|
| 15 | + private store: LocalStorageService, |
|---|
| 16 | + private http: Http) { |
|---|
| 17 | + |
|---|
| 18 | + } |
|---|
| 19 | + |
|---|
| 20 | + public login(username: string, password: string) : Observable<string> { |
|---|
| 21 | + let params = new URLSearchParams(); |
|---|
| 22 | + params.append('username', username); |
|---|
| 23 | + params.append('password', password); |
|---|
| 24 | + let options = new RequestOptions({ headers: new Headers({ "Content-Type": "application/x-www-form-urlencoded" })}); |
|---|
| 25 | + return this.http.post('user/login', params, options) |
|---|
| 26 | + .map((res: Response) => { |
|---|
| 27 | + let data = res.json(); |
|---|
| 28 | + this.store.set('username', username); |
|---|
| 29 | + this.store.set('token', data.token); |
|---|
| 30 | + return <string>data.token; |
|---|
| 31 | + }) |
|---|
| 32 | + .catch(this.handleError); |
|---|
| 33 | + } |
|---|
| 34 | + |
|---|
| 35 | + isLoggedIn() : Observable<Boolean> { |
|---|
| 36 | + if (!this.existsToken()) { |
|---|
| 37 | + return Observable.of(false); |
|---|
| 38 | + } |
|---|
| 39 | + var token = this.store.get(SECURIS_TOKEN); |
|---|
| 40 | + return this.http.get('check', new RequestOptions({ headers: new Headers({ 'X-SECURIS-TOKEN': token }) })) |
|---|
| 41 | + .map((res: Response) => { |
|---|
| 42 | + let body = res.json(); |
|---|
| 43 | + if (body.valid) { |
|---|
| 44 | + this.store.set('user', body.user); |
|---|
| 45 | + } |
|---|
| 46 | + return body.valid; |
|---|
| 47 | + }) |
|---|
| 48 | + .catch(this.handleError) |
|---|
| 49 | + .catch(() => Observable.of(false)); |
|---|
| 50 | + } |
|---|
| 51 | + |
|---|
| 52 | + existsToken() : Boolean { |
|---|
| 53 | + return this.store.get(SECURIS_TOKEN) !== null; |
|---|
| 54 | + } |
|---|
| 55 | + |
|---|
| 56 | + logout() : void { |
|---|
| 57 | + this.store.remove('user', 'token'); |
|---|
| 58 | + this.router.navigate(['Login']); |
|---|
| 59 | + } |
|---|
| 60 | + |
|---|
| 61 | + private handleError (error: Response | any) { |
|---|
| 62 | + // In a real world app, we might use a remote logging infrastructure |
|---|
| 63 | + let errMsg: string; |
|---|
| 64 | + if (error instanceof Response) { |
|---|
| 65 | + const body = error.json() || ''; |
|---|
| 66 | + const err = body.error || JSON.stringify(body); |
|---|
| 67 | + errMsg = `${error.status} - ${error.statusText || ''} ${err}`; |
|---|
| 68 | + } else { |
|---|
| 69 | + errMsg = error.message ? error.message : error.toString(); |
|---|
| 70 | + } |
|---|
| 71 | + console.error(errMsg); |
|---|
| 72 | + return Observable.throw(errMsg); |
|---|
| 73 | + } |
|---|
| 74 | + |
|---|
| 75 | +} |
|---|
| 76 | + |
|---|
| .. | .. |
|---|
| 1 | +export const environment = { |
|---|
| 2 | + production: false |
|---|
| 3 | +}; |
|---|
| .. | .. |
|---|
| 1 | +export const environment = { |
|---|
| 2 | + production: true |
|---|
| 3 | +}; |
|---|
| .. | .. |
|---|
| 1 | +export const environment = { |
|---|
| 2 | + production: false |
|---|
| 3 | +}; |
|---|
| .. | .. |
|---|
| 1 | +{ |
|---|
| 2 | +"": "", |
|---|
| 3 | +"": "" |
|---|
| 4 | +} |
|---|
| .. | .. |
|---|
| 1 | +{ |
|---|
| 2 | +"": "", |
|---|
| 3 | +"": "" |
|---|
| 4 | +} |
|---|
| .. | .. |
|---|
| 1 | +{ |
|---|
| 2 | +"": "", |
|---|
| 3 | +"": "" |
|---|
| 4 | +} |
|---|
| .. | .. |
|---|
| 4 | 4 | import { AppModule } from './app/app.module'; |
|---|
| 5 | 5 | |
|---|
| 6 | 6 | import { enableProdMode } from '@angular/core'; |
|---|
| 7 | | -enableProdMode(); |
|---|
| 7 | +import { environment } from './environments/environment'; |
|---|
| 8 | + |
|---|
| 9 | +if (environment.production) { |
|---|
| 10 | + enableProdMode(); |
|---|
| 11 | +} |
|---|
| 8 | 12 | |
|---|
| 9 | 13 | platformBrowserDynamic().bootstrapModule(AppModule); |
|---|
| .. | .. |
|---|
| 9 | 9 | var COVALENT_LIBS = ['core', 'http', 'dynamic-forms']; |
|---|
| 10 | 10 | var mapping = { |
|---|
| 11 | 11 | // our app is within the app folder |
|---|
| 12 | | - main: 'src/main.js', |
|---|
| 12 | + main: 'src/main.js', |
|---|
| 13 | 13 | 'app': 'src/app', |
|---|
| 14 | + 'environments': 'src/environments', |
|---|
| 14 | 15 | |
|---|
| 15 | 16 | // other libraries |
|---|
| 16 | 17 | 'rxjs': 'npm:rxjs', |
|---|
| 18 | + 'ng2-toastr': 'npm:ng2-toastr', |
|---|
| 19 | + 'angular-2-local-storage': 'npm:angular-2-local-storage/dist', |
|---|
| 17 | 20 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' |
|---|
| 18 | 21 | } |
|---|
| 19 | 22 | |
|---|
| .. | .. |
|---|
| 32 | 35 | }, |
|---|
| 33 | 36 | map: mapping, |
|---|
| 34 | 37 | packages: { |
|---|
| 38 | + 'environments': { |
|---|
| 39 | + defaultExtension: 'js' |
|---|
| 40 | + }, |
|---|
| 35 | 41 | 'app': { |
|---|
| 36 | 42 | defaultExtension: 'js' |
|---|
| 37 | 43 | }, |
|---|
| 38 | 44 | 'rxjs': { main: 'index' }, |
|---|
| 45 | + 'angular-2-local-storage': { main: 'index', defaultExtension: 'js' }, |
|---|
| 46 | + 'ng2-toastr': { defaultExtension: 'js' } |
|---|
| 39 | 47 | } |
|---|
| 40 | 48 | }); |
|---|
| 41 | 49 | |
|---|