From 7c04274b5ad8f2818d39910ff790aed7db9c349c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ca=C3=B1izares=20Est=C3=A9vez?= Date: Thu, 17 Nov 2016 18:29:47 +0100 Subject: [PATCH 1/3] service in spa to retrieve data from catalog api, project structure simplified --- .../Client/modules/app.component.ts | 12 +- .../modules/catalog/catalog.component.ts | 27 ++- .../Client/modules/catalog/catalog.module.ts | 10 +- .../Client/modules/catalog/catalog.service.ts | 15 ++ .../shared/layout/footer.component.html | 2 +- .../modules/shared/models/catalog.model.ts | 6 + .../shared/models/catalogItem.model.ts | 3 + .../modules/shared/models/user.model.spec.ts | 13 -- .../shared/services/api-gateway.service.ts | 207 ------------------ .../api-translation-loader.service.ts | 23 -- .../shared/services/content.service.ts | 13 -- .../modules/shared/services/data.service.ts | 36 ++- .../services/http-error-handler.service.ts | 25 --- .../Client/modules/shared/shared.module.ts | 12 +- .../config/webpack.config.js | 2 +- .../eShopOnContainers.WebSPA/package.json | 3 +- 16 files changed, 90 insertions(+), 319 deletions(-) create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.spec.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-gateway.service.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-translation-loader.service.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/content.service.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/http-error-handler.service.ts diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts index fcd39952e..b32e8929b 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts @@ -1,7 +1,6 @@ import { Title } from '@angular/platform-browser'; import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { TranslateService } from 'ng2-translate/ng2-translate'; import { DataService } from './shared/services/data.service'; @@ -18,20 +17,15 @@ import { DataService } from './shared/services/data.service'; export class AppComponent implements OnInit { - constructor(private translate: TranslateService, private titleService: Title) { - // this language will be used as a fallback when a translation isn't found in the current language - translate.setDefaultLang('en'); + constructor(private titleService: Title) { - // the lang to use, if the lang isn't available, it will use the current loader to get them - translate.use('en'); } ngOnInit() { - this.translate.get('title') - .subscribe(title => this.setTitle(title)); + } public setTitle(newTitle: string) { - this.titleService.setTitle(newTitle); + this.titleService.setTitle('eShopOnContainers'); } } diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts index 53ca23abe..a3772900c 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts @@ -1,15 +1,28 @@ import { Component, OnInit } from '@angular/core'; +import { CatalogService } from './catalog.service'; +import { Catalog } from '../shared/models/catalog.model'; +import { CatalogItem } from '../shared/models/catalogItem.model'; @Component({ - selector: 'appc-catalog', - styleUrls: ['./catalog.component.scss'], - templateUrl: './catalog.component.html' + selector: 'appc-catalog', + styleUrls: ['./catalog.component.scss'], + templateUrl: './catalog.component.html' }) export class CatalogComponent implements OnInit { - constructor() { } + private brands: any[]; + private types: any[]; + private items: CatalogItem[]; + private filteredItems: any[]; + private catalog: Catalog; - ngOnInit() { - console.log('catalog component loaded'); - } + constructor(private service: CatalogService) { } + ngOnInit() { + console.log('catalog component loaded'); + this.service.getCatalog().subscribe((catalog: Catalog) => { + this.catalog = catalog; + this.items = catalog.data; + console.log(this.items.length + ' catalog items retrieved from api'); + }); + } } diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts index 95e541939..4ecc504b7 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts @@ -1,11 +1,13 @@ -import { NgModule } from '@angular/core'; +import { NgModule } from '@angular/core'; -import { CatalogComponent } from './catalog.component'; -import { routing } from './catalog.routes'; +import { CatalogComponent } from './catalog.component'; +import { routing } from './catalog.routes'; +import { CatalogService } from './catalog.service'; @NgModule({ imports: [routing], - declarations: [CatalogComponent] + declarations: [CatalogComponent], + providers: [CatalogService] }) export class CatalogModule { } diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts new file mode 100644 index 000000000..8932531da --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; + +import { DataService } from '../shared/services/data.service'; + +@Injectable() +export class CatalogService { + private catalogUrl: string = 'http://eshopcontainers:5101/api/v1/catalog/items'; + + constructor(private service: DataService) { + } + + getCatalog(){ + return this.service.get(this.catalogUrl); + } +} \ No newline at end of file diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/footer.component.html b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/footer.component.html index 977840161..11a669057 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/footer.component.html +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/footer.component.html @@ -2,7 +2,7 @@

- © 2015-2016 {{'title' | translate}} Company + © 2015-2016 {{'title'}} Company

diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts new file mode 100644 index 000000000..7fe3dec15 --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts @@ -0,0 +1,6 @@ +import {CatalogItem} from './catalogItem.model'; + +export class Catalog { + constructor(public pageIndex: number, public data: CatalogItem[], public pageSize: number, public count: number) { + } +} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts new file mode 100644 index 000000000..c89193e20 --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts @@ -0,0 +1,3 @@ +export class CatalogItem { + constructor(public Id: string, public Name: string, public Description: string, public Price: number, public PictureUri: string, public CatalogBrandId: number, public CatalogBrand: string, public CatalogTypeId: number, public CatalogType: string) { } +} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.spec.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.spec.ts deleted file mode 100644 index b38cd5490..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { User } from './user.model'; -// todo: I dont think user follows angular style guides - -describe('User Model', () => { - it('has displayName', () => { - let userModel: User = {displayName: 'test', roles: ['1']}; - expect(userModel.displayName).toEqual('test'); - }); - it('has displayName', () => { - let userModel: User = {displayName: 'test', roles: ['admin']}; - expect(userModel.roles[0]).toEqual('admin'); - }); -}); diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-gateway.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-gateway.service.ts deleted file mode 100644 index 6df54875e..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-gateway.service.ts +++ /dev/null @@ -1,207 +0,0 @@ -// CREDIT: -// The vast majority of this code came right from Ben Nadel's post: -// http://www.bennadel.com/blog/3047-creating-specialized-http-clients-in-angular-2-beta-8.htm -// -// My updates are mostly adapting it for Typescript: -// 1. Importing required modules -// 2. Adding type notations -// 3. Using the 'fat-arrow' syntax to properly scope in-line functions -// -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/catch'; -import 'rxjs/add/operator/finally'; - -import { Injectable } from '@angular/core'; -import { Http, Response, RequestOptions, RequestMethod, URLSearchParams } from '@angular/http'; -import { Observable } from 'rxjs/Observable'; -import { Subject } from 'rxjs/Subject'; - -import { HttpErrorHandlerService } from './http-error-handler.service'; - -// Import the rxjs operators we need (in a production app you'll -// probably want to import only the operators you actually use) -// -export class ApiGatewayOptions { - method: RequestMethod; - url: string; - headers: any = {}; - params = {}; - data = {}; -} - - -@Injectable() -export class ApiGatewayService { - - // Define the internal Subject we'll use to push the command count - private pendingCommandsSubject = new Subject(); - private pendingCommandCount = 0; - - // Provide the *public* Observable that clients can subscribe to - private pendingCommands$: Observable; - - constructor(private http: Http, private httpErrorHandler: HttpErrorHandlerService) { - this.pendingCommands$ = this.pendingCommandsSubject.asObservable(); - } - - // I perform a GET request to the API, appending the given params - // as URL search parameters. Returns a stream. - get(url: string, params: any): Observable { - let options = new ApiGatewayOptions(); - options.method = RequestMethod.Get; - options.url = url; - options.params = params; - return this.request(options); - } - - // I perform a POST request to the API. If both the params and data - // are present, the params will be appended as URL search parameters - // and the data will be serialized as a JSON payload. If only the - // data is present, it will be serialized as a JSON payload. Returns - // a stream. - post(url: string, data: any, params: any): Observable { - if (!data) { - data = params; - params = {}; - } - let options = new ApiGatewayOptions(); - options.method = RequestMethod.Post; - options.url = url; - options.params = params; - options.data = data; - return this.request(options); - } - - - private request(options: ApiGatewayOptions): Observable { - options.method = (options.method || RequestMethod.Get); - options.url = (options.url || ''); - options.headers = (options.headers || {}); - options.params = (options.params || {}); - options.data = (options.data || {}); - - this.interpolateUrl(options); - this.addXsrfToken(options); - this.addContentType(options); - // TODO add auth token when available - // this.addAuthToken(options); - - let requestOptions = new RequestOptions(); - requestOptions.method = options.method; - requestOptions.url = options.url; - requestOptions.headers = options.headers; - requestOptions.search = this.buildUrlSearchParams(options.params); - requestOptions.body = JSON.stringify(options.data); - - let isCommand = (options.method !== RequestMethod.Get); - - if (isCommand) { - this.pendingCommandsSubject.next(++this.pendingCommandCount); - } - - let stream = this.http.request(options.url, requestOptions) - .catch((error: any) => { - this.httpErrorHandler.handle(error); - return Observable.throw(error); - }) - .map(this.unwrapHttpValue) - .catch((error: any) => { - return Observable.throw(this.unwrapHttpError(error)); - }) - .finally(() => { - if (isCommand) { - this.pendingCommandsSubject.next(--this.pendingCommandCount); - } - }); - - return stream; - } - - - private addContentType(options: ApiGatewayOptions): ApiGatewayOptions { - if (options.method !== RequestMethod.Get) { - options.headers['Content-Type'] = 'application/json; charset=UTF-8'; - } - return options; - } - - private addAuthToken(options: ApiGatewayOptions): ApiGatewayOptions { - options.headers.Authorization = 'Bearer ' + JSON.parse(sessionStorage.getItem('accessToken')); - return options; - } - - private extractValue(collection: any, key: string): any { - let value = collection[key]; - delete (collection[key]); - return value; - } - - private addXsrfToken(options: ApiGatewayOptions): ApiGatewayOptions { - let xsrfToken = this.getXsrfCookie(); - if (xsrfToken) { - options.headers['X-XSRF-TOKEN'] = xsrfToken; - } - return options; - } - - private getXsrfCookie(): string { - let matches = document.cookie.match(/\bXSRF-TOKEN=([^\s;]+)/); - try { - return (matches && decodeURIComponent(matches[1])); - } catch (decodeError) { - return (''); - } - } - - private addCors(options: ApiGatewayOptions): ApiGatewayOptions { - options.headers['Access-Control-Allow-Origin'] = '*'; - return options; - } - - private buildUrlSearchParams(params: any): URLSearchParams { - let searchParams = new URLSearchParams(); - for (let key in params) { - if (params.hasOwnProperty(key)) { - searchParams.append(key, params[key]); - } - } - return searchParams; - } - - private interpolateUrl(options: ApiGatewayOptions): ApiGatewayOptions { - options.url = options.url.replace(/:([a-zA-Z]+[\w-]*)/g, ($0, token) => { - // Try to move matching token from the params collection. - if (options.params.hasOwnProperty(token)) { - return (this.extractValue(options.params, token)); - } - // Try to move matching token from the data collection. - if (options.data.hasOwnProperty(token)) { - return (this.extractValue(options.data, token)); - } - // If a matching value couldn't be found, just replace - // the token with the empty string. - return (''); - }); - // Clean up any repeating slashes. - options.url = options.url.replace(/\/{2,}/g, '/'); - // Clean up any trailing slashes. - options.url = options.url.replace(/\/+$/g, ''); - - return options; - } - - private unwrapHttpError(error: any): any { - try { - return (error.json()); - } catch (jsonError) { - return ({ - code: -1, - message: 'An unexpected error occurred.' - }); - } - } - - private unwrapHttpValue(value: Response): any { - return (value.json()); - } -} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-translation-loader.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-translation-loader.service.ts deleted file mode 100644 index 2105706b9..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/api-translation-loader.service.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs/Rx'; -import { TranslateLoader } from 'ng2-translate/ng2-translate'; -import { MissingTranslationHandler, MissingTranslationHandlerParams } from 'ng2-translate/ng2-translate'; - -import { ContentService } from './content.service'; - -@Injectable() -export class ApiTranslationLoader implements TranslateLoader { - - constructor(private cs: ContentService) { } - - getTranslation(lang: string): Observable { - return this.cs.get(lang); - } -} - -@Injectable() -export class CustomMissingTranslationHandler implements MissingTranslationHandler { - handle(params: MissingTranslationHandlerParams) { - return params.key; - } -} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/content.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/content.service.ts deleted file mode 100644 index 8f67ec197..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/content.service.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Injectable } from '@angular/core'; - -import { DataService } from './data.service'; - -@Injectable() -export class ContentService { - - constructor(public dataService: DataService) { } - - get(lang?: string): any { - return this.dataService.get('api/content?lang=' + (lang ? lang : 'en')); - } -} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts index 1b08aeada..8fca8fe26 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts @@ -1,17 +1,47 @@ import { Injectable } from '@angular/core'; +import { Http, Response, RequestOptionsArgs, RequestMethod, Headers } from '@angular/http'; -import { ApiGatewayService } from './api-gateway.service'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/observable/throw'; +import { Observer } from 'rxjs/Observer'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/catch'; @Injectable() export class DataService { - constructor(public http: ApiGatewayService) { } + constructor(public http: Http) { } get(url: string, params?: any) { - return this.http.get(url, undefined); + let options: RequestOptionsArgs = {}; + options.headers = new Headers(); + this.addCors(options); + + return this.http.get(url, options).map(((res: Response) => { + return res.json(); + })).catch(this.handleError); } post(url: string, data: any, params?: any) { return this.http.post(url, data, params); } + + private addCors(options: RequestOptionsArgs): RequestOptionsArgs { + options.headers.append('Access-Control-Allow-Origin', '*'); + return options; + } + + private handleError(error: any) { + console.error('server error:', error); + if (error instanceof Response) { + let errMessage = ''; + try { + errMessage = error.json().error; + } catch (err) { + errMessage = error.statusText; + } + return Observable.throw(errMessage); + } + return Observable.throw(error || 'Node.js server error'); + } } diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/http-error-handler.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/http-error-handler.service.ts deleted file mode 100644 index 23f4825f1..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/http-error-handler.service.ts +++ /dev/null @@ -1,25 +0,0 @@ -// CREDIT: -// The vast majority of this code came right from Ben Nadel's post: -// http://www.bennadel.com/blog/3047-creating-specialized-http-clients-in-angular-2-beta-8.htm -// -// My updates are mostly adapting it for Typescript: -// 1. Importing required modules -// 2. Adding type notations -// 3. Using the 'fat-arrow' syntax to properly scope in-line functions -// -import { Injectable } from '@angular/core'; -import { Router } from '@angular/router'; - -@Injectable() -export class HttpErrorHandlerService { - - constructor(private _router: Router) { } - - handle(error: any) { - if (error.status === 401) { - sessionStorage.clear(); - // window.location.href = 'login'; - this._router.navigate(['Login']); - } - } -} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts index b4e717f36..67b80ed8a 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts @@ -4,7 +4,6 @@ import { FormsModule, ReactiveFormsModule, FormBuilder } from '@angular/forms'; import { RouterModule } from '@angular/router'; import { HttpModule, JsonpModule } from '@angular/http'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { TranslateModule, TranslateLoader } from 'ng2-translate/ng2-translate'; import { PageHeadingComponent } from './directives/page-heading.directive'; import { DynamicFormComponent } from './forms/dynamic-form.component'; @@ -17,11 +16,7 @@ import { HeaderComponent } from './layout/header.component'; import { FooterComponent } from './layout/footer.component'; // Services import { DataService } from './services/data.service'; -import { ApiGatewayService } from './services/api-gateway.service'; import { AuthService } from './services/auth.service'; -import { HttpErrorHandlerService } from './services/http-error-handler.service'; -import { ApiTranslationLoader } from './services/api-translation-loader.service'; -import { ContentService } from './services/content.service'; import { UtilityService } from './services/utility.service'; import { UppercasePipe } from './pipes/uppercase.pipe'; @@ -34,8 +29,7 @@ import { UppercasePipe } from './pipes/uppercase.pipe'; NgbModule.forRoot(), // No need to export as these modules don't expose any components/directive etc' HttpModule, - JsonpModule, - TranslateModule.forRoot({ provide: TranslateLoader, useClass: ApiTranslationLoader }) + JsonpModule ], declarations: [ DynamicFormComponent, @@ -54,7 +48,6 @@ import { UppercasePipe } from './pipes/uppercase.pipe'; ReactiveFormsModule, RouterModule, NgbModule, - TranslateModule, // Providers, Components, directive, pipes DynamicFormComponent, DynamicFormControlComponent, @@ -73,11 +66,8 @@ export class SharedModule { ngModule: SharedModule, providers: [ // Providers - HttpErrorHandlerService, - ApiGatewayService, AuthService, DataService, - ContentService, FormControlService, UtilityService ] diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/config/webpack.config.js b/src/Web/WebSPA/eShopOnContainers.WebSPA/config/webpack.config.js index 780f9955f..77e8afc07 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/config/webpack.config.js +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/config/webpack.config.js @@ -6,7 +6,7 @@ var extractCSS = new ExtractTextPlugin('styles.css'); var ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin; var devConfig = require('./webpack.config.dev'); var prodConfig = require('./webpack.config.prod'); -var isDevelopment = process.env.ASPNETCORE_ENVIRONMENT === 'Production'; +var isDevelopment = process.env.ASPNETCORE_ENVIRONMENT === 'Development'; console.log("==========Dev Mode = " + isDevelopment + " ============" ) diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/package.json b/src/Web/WebSPA/eShopOnContainers.WebSPA/package.json index 84c93350d..066f39baa 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/package.json +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/package.json @@ -35,7 +35,7 @@ "build:prod": "npm run setprod && npm run clean:dist && npm run build:vendor && npm run build:main", "lint": "npm run tslint \"Client/**/*.ts\"", "docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./Client/", - "version": "npm run build", + "version": "npm run build" }, "dependencies": { "@angular/common": "2.1.2", @@ -55,7 +55,6 @@ "core-js": "2.4.1", "font-awesome": "4.6.3", "isomorphic-fetch": "2.2.1", - "ng2-translate": "4.0.0", "normalize.css": "5.0.0", "preboot": "4.5.2", "rxjs": "5.0.0-beta.12", From 141a9a22466093f4c0288bc2c62aada710819c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ca=C3=B1izares=20Est=C3=A9vez?= Date: Fri, 18 Nov 2016 15:55:40 +0100 Subject: [PATCH 2/3] catalog integration with real service in Spa web application (pagination, brand & type filter, etc.). --- .../Client/modules/app.module.ts | 1 - .../modules/catalog/catalog.component.html | 35 +++----- .../modules/catalog/catalog.component.ts | 86 ++++++++++++++++--- .../Client/modules/catalog/catalog.module.ts | 6 +- .../Client/modules/catalog/catalog.service.ts | 37 +++++++- .../shared/components/pager/pager.html | 29 +++++++ .../shared/components/pager/pager.scss | 0 .../modules/shared/components/pager/pager.ts | 33 +++++++ .../modules/shared/layout/header.component.ts | 4 +- .../modules/shared/models/catalog.model.ts | 10 ++- .../shared/models/catalogBrand.model.ts | 4 + .../shared/models/catalogItem.model.ts | 12 ++- .../shared/models/catalogType.model.ts | 4 + .../shared/models/operation-result.model.ts | 3 - .../modules/shared/models/pager.model.ts | 6 ++ .../modules/shared/models/user.model.ts | 4 - .../modules/shared/services/auth.service.ts | 37 -------- .../modules/shared/services/data.service.ts | 14 +-- .../Client/modules/shared/shared.module.ts | 11 ++- 19 files changed, 230 insertions(+), 106 deletions(-) create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.html create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.scss create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.ts create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogBrand.model.ts create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogType.model.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/operation-result.model.ts create mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/pager.model.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.ts delete mode 100644 src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/auth.service.ts diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.module.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.module.ts index 2716bb5a7..458999ebf 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.module.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.module.ts @@ -15,7 +15,6 @@ import { CatalogModule } from './catalog/catalog.module'; imports: [ BrowserModule, routing, - // FormsModule, HttpModule, // Only module that app module loads SharedModule.forRoot(), diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.html b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.html index ccfbe5e48..81fa2fb73 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.html +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.html @@ -7,36 +7,21 @@
- + - +
+
+
-
- +
+
-
- - -
-
- - -
-
- - -
-
- - -
-
\ No newline at end of file +
+ \ No newline at end of file diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts index a3772900c..e4ec52ef0 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts @@ -1,28 +1,86 @@ -import { Component, OnInit } from '@angular/core'; -import { CatalogService } from './catalog.service'; -import { Catalog } from '../shared/models/catalog.model'; -import { CatalogItem } from '../shared/models/catalogItem.model'; +import { Component, OnInit } from '@angular/core'; +import { CatalogService } from './catalog.service'; +import { ICatalog } from '../shared/models/catalog.model'; +import { ICatalogItem } from '../shared/models/catalogItem.model'; +import { ICatalogType } from '../shared/models/catalogType.model'; +import { ICatalogBrand } from '../shared/models/catalogBrand.model'; +import { IPager } from '../shared/models/pager.model'; @Component({ - selector: 'appc-catalog', + selector: 'esh-catalog', styleUrls: ['./catalog.component.scss'], templateUrl: './catalog.component.html' }) export class CatalogComponent implements OnInit { - private brands: any[]; - private types: any[]; - private items: CatalogItem[]; - private filteredItems: any[]; - private catalog: Catalog; + brands: ICatalogBrand[]; + types: ICatalogType[]; + catalog: ICatalog; + brandSelected: number; + typeSelected: number; + paginationInfo: IPager; constructor(private service: CatalogService) { } ngOnInit() { - console.log('catalog component loaded'); - this.service.getCatalog().subscribe((catalog: Catalog) => { + this.getBrands(); + this.getCatalog(10,0); + this.getTypes(); + } + + onFilterApplied(event: any) { + event.preventDefault(); + this.getCatalog(this.paginationInfo.itemsPage, this.paginationInfo.actualPage, this.brandSelected, this.typeSelected); + } + + onBrandFilterChanged(event: any, value: number) { + event.preventDefault(); + this.brandSelected = value; + } + + onTypeFilterChanged(event: any, value: number) { + event.preventDefault(); + this.typeSelected = value; + } + + onPageChanged(value: any) { + console.log('catalog pager event fired' + value); + event.preventDefault(); + this.paginationInfo.actualPage = value; + this.getCatalog(this.paginationInfo.itemsPage, value); + } + + getCatalog(pageSize:number, pageIndex: number, brand?: number, type?: number) { + this.service.getCatalog(brand, type).subscribe(catalog => { this.catalog = catalog; - this.items = catalog.data; - console.log(this.items.length + ' catalog items retrieved from api'); + console.log('catalog items retrieved: ' + catalog.count); + + this.paginationInfo = { + actualPage : catalog.pageIndex, + itemsPage : catalog.pageSize, + totalItems : catalog.count, + totalPages : (catalog.count / catalog.pageSize) + }; + + console.log(this.paginationInfo); + }); + } + + getTypes() { + this.service.getTypes().subscribe(types => { + this.types = types; + let alltypes = { id: null, type: 'All' }; + this.types.unshift(alltypes); + console.log('types retrieved: ' + types.length); + }); + } + + getBrands() { + this.service.getBrands().subscribe(brands => { + this.brands = brands; + let allBrands = { id: null, brand: 'All' }; + this.brands.unshift(allBrands); + console.log('brands retrieved: ' + brands.length); }); } } + diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts index 4ecc504b7..64e961d03 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.module.ts @@ -1,12 +1,16 @@ import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { SharedModule } from '../shared/shared.module'; import { CatalogComponent } from './catalog.component'; import { routing } from './catalog.routes'; import { CatalogService } from './catalog.service'; +import { Pager } from '../shared/components/pager/pager'; + @NgModule({ - imports: [routing], + imports: [routing, BrowserModule, SharedModule], declarations: [CatalogComponent], providers: [CatalogService] }) diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts index 8932531da..a5e92133a 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts @@ -1,15 +1,48 @@ import { Injectable } from '@angular/core'; +import { Response } from '@angular/http'; import { DataService } from '../shared/services/data.service'; +import { ICatalog } from '../shared/models/catalog.model'; +import { ICatalogBrand } from '../shared/models/catalogBrand.model'; +import { ICatalogType } from '../shared/models/catalogType.model'; + +import 'rxjs/Rx'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/observable/throw'; +import { Observer } from 'rxjs/Observer'; +import 'rxjs/add/operator/map'; @Injectable() export class CatalogService { private catalogUrl: string = 'http://eshopcontainers:5101/api/v1/catalog/items'; + private brandUrl: string = 'http://eshopcontainers:5101/api/v1/catalog/catalogbrands'; + private typesUrl: string = 'http://eshopcontainers:5101/api/v1/catalog/catalogtypes'; constructor(private service: DataService) { } - getCatalog(){ - return this.service.get(this.catalogUrl); + getCatalog(pageIndex: number, pageSize: number, brand: number, type: number): Observable { + var url = this.catalogUrl; + if (brand || type) { + url = this.catalogUrl + '/type/' + ((type) ? type.toString() : 'null') + '/brand/' + ((brand) ? brand.toString() : 'null'); + } + + url = url + '?pageIndex=' + pageIndex + '&pageSize=' + pageSize; + + return this.service.get(url).map((response: Response) => { + return response.json(); + }); + } + + getBrands(): Observable { + return this.service.get(this.brandUrl).map((response: Response) => { + return response.json(); + }); } + + getTypes(): Observable { + return this.service.get(this.typesUrl).map((response: Response) => { + return response.json(); + }); + }; } \ No newline at end of file diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.html b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.html new file mode 100644 index 000000000..3aa344d6f --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.html @@ -0,0 +1,29 @@ +
+
+ +
+
Showing {{model?.itemsPage}} of {{model?.totalItems}} products - Page {{model?.actualPage}} - {{model?.totalPages}}
+
+ +
+
\ No newline at end of file diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.scss b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.ts new file mode 100644 index 000000000..41910a0ca --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/components/pager/pager.ts @@ -0,0 +1,33 @@ +import { Component, OnInit, Output, Input, EventEmitter } from '@angular/core'; + +import { IPager } from '../../models/pager.model'; + +@Component({ + selector: 'esh-pager', + templateUrl: './pager.html', + styleUrls: ['./pager.scss'] +}) +export class Pager implements OnInit { + + @Output() + changed: EventEmitter = new EventEmitter(); + + @Input() + model: IPager; + + ngOnInit() { + console.log(this.model); + } + + onNextClicked(event: any) { + event.preventDefault(); + console.log('Pager Next Clicked'); + this.changed.emit(this.model.actualPage + 1); + } + + onPreviousCliked(event: any) { + event.preventDefault(); + this.changed.emit(this.model.actualPage - 1); + } + +} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/header.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/header.component.ts index 6e23eb2c0..fb69eb730 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/header.component.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/layout/header.component.ts @@ -1,8 +1,6 @@ import { Component, Inject } from '@angular/core'; import { Router } from '@angular/router'; -import { AuthService } from '../services/auth.service'; - @Component({ selector: 'appc-header', styleUrls: ['./header.component.scss'], @@ -10,7 +8,7 @@ import { AuthService } from '../services/auth.service'; }) export class HeaderComponent { isCollapsed: boolean = true; - constructor(private router: Router, private authService: AuthService) { } + constructor(private router: Router) { } toggleNav() { this.isCollapsed = !this.isCollapsed; diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts index 7fe3dec15..72cc38009 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalog.model.ts @@ -1,6 +1,8 @@ -import {CatalogItem} from './catalogItem.model'; +import {ICatalogItem} from './catalogItem.model'; -export class Catalog { - constructor(public pageIndex: number, public data: CatalogItem[], public pageSize: number, public count: number) { - } +export interface ICatalog { + pageIndex: number + data: ICatalogItem[] + pageSize: number + count: number } diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogBrand.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogBrand.model.ts new file mode 100644 index 000000000..3f7a183da --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogBrand.model.ts @@ -0,0 +1,4 @@ +export interface ICatalogBrand { + id: number + brand: string +} \ No newline at end of file diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts index c89193e20..521df03a7 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogItem.model.ts @@ -1,3 +1,11 @@ -export class CatalogItem { - constructor(public Id: string, public Name: string, public Description: string, public Price: number, public PictureUri: string, public CatalogBrandId: number, public CatalogBrand: string, public CatalogTypeId: number, public CatalogType: string) { } +export interface ICatalogItem { + id: string; + name: string; + description: string; + price: number; + pictureUri: string; + catalogBrandId: number; + catalogBrand: string; + catalogTypeId: number; + catalogType: string; } diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogType.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogType.model.ts new file mode 100644 index 000000000..53a2a2ad3 --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/catalogType.model.ts @@ -0,0 +1,4 @@ +export interface ICatalogType { + id: number + type: string +} \ No newline at end of file diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/operation-result.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/operation-result.model.ts deleted file mode 100644 index 6a98bfafa..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/operation-result.model.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class OperationResult { - constructor(public succeeded: boolean, public message: string) { } -} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/pager.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/pager.model.ts new file mode 100644 index 000000000..7d10b271b --- /dev/null +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/pager.model.ts @@ -0,0 +1,6 @@ +export interface IPager { + itemsPage: number, + totalItems: number, + actualPage: number, + totalPages: number +} \ No newline at end of file diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.ts deleted file mode 100644 index 7b1dbbc9c..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/user.model.ts +++ /dev/null @@ -1,4 +0,0 @@ -export class User { - constructor(public displayName: string, public roles: string[]) { - } -} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/auth.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/auth.service.ts deleted file mode 100644 index 2f3d8ed64..000000000 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/auth.service.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Router } from '@angular/router'; - -import { DataService } from './data.service'; -import { User } from '../models/user.model'; - -@Injectable() -export class AuthService { - - constructor(private router: Router) { } - - logout() { - sessionStorage.clear(); - this.router.navigate(['/login']); - } - - isLoggedIn(): boolean { - return this.user(undefined) !== undefined; - } - - user(user: User): User { - if (user) { - sessionStorage.setItem('user', JSON.stringify(user)); - } - let userData = JSON.parse(sessionStorage.getItem('user')); - if (userData) { - user = new User(userData.displayName, userData.roles); - } - return user ? user : undefined; - } - - setAuth(res: any): void { - if (res && res.user) { - sessionStorage.setItem('user', JSON.stringify(res.user)); - } - } -} diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts index 8fca8fe26..d1e609e9e 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/data.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { Http, Response, RequestOptionsArgs, RequestMethod, Headers } from '@angular/http'; +import 'rxjs/Rx'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/throw'; import { Observer } from 'rxjs/Observer'; @@ -10,16 +11,17 @@ import 'rxjs/add/operator/catch'; @Injectable() export class DataService { - constructor(public http: Http) { } + constructor(private http: Http) { } - get(url: string, params?: any) { + get(url: string, params?: any): Observable { let options: RequestOptionsArgs = {}; options.headers = new Headers(); this.addCors(options); - return this.http.get(url, options).map(((res: Response) => { - return res.json(); - })).catch(this.handleError); + return this.http.get(url, options).map( + (res: Response) => { + return res; + }).catch(this.handleError); } post(url: string, data: any, params?: any) { @@ -42,6 +44,6 @@ export class DataService { } return Observable.throw(errMessage); } - return Observable.throw(error || 'Node.js server error'); + return Observable.throw(error || 'server error'); } } diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts index 67b80ed8a..9c9395572 100644 --- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts +++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts @@ -16,10 +16,12 @@ import { HeaderComponent } from './layout/header.component'; import { FooterComponent } from './layout/footer.component'; // Services import { DataService } from './services/data.service'; -import { AuthService } from './services/auth.service'; import { UtilityService } from './services/utility.service'; import { UppercasePipe } from './pipes/uppercase.pipe'; +//Components: +import {Pager } from './components/pager/pager'; + @NgModule({ imports: [ CommonModule, @@ -39,7 +41,8 @@ import { UppercasePipe } from './pipes/uppercase.pipe'; FooterComponent, HeaderComponent, PageHeadingComponent, - UppercasePipe + UppercasePipe, + Pager ], exports: [ // Modules @@ -56,7 +59,8 @@ import { UppercasePipe } from './pipes/uppercase.pipe'; FooterComponent, HeaderComponent, PageHeadingComponent, - UppercasePipe + UppercasePipe, + Pager ] }) @@ -66,7 +70,6 @@ export class SharedModule { ngModule: SharedModule, providers: [ // Providers - AuthService, DataService, FormControlService, UtilityService From b0cc1a14d7f3ab8d7436d82413f215252f8e10b6 Mon Sep 17 00:00:00 2001 From: Unai Date: Mon, 21 Nov 2016 10:02:52 +0100 Subject: [PATCH 3/3] Minor refactoring and review on ordering bc --- src/Services/Ordering/Ordering.API/Startup.cs | 43 ++++++++----------- .../Ordering/Ordering.API/project.json | 1 + 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 605bcdd59..8e003d8e5 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -23,8 +23,15 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) - .AddEnvironmentVariables(); + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); + + if (env.IsDevelopment()) + { + builder.AddUserSecrets(); + } + + builder.AddEnvironmentVariables(); + Configuration = builder.Build(); } @@ -37,28 +44,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API // Add framework services. services.AddMvc(); - //Add EF Core Context (UnitOfWork) - //SQL LocalDB - // var connString = @"Server=(localdb)\mssqllocaldb;Database=Microsoft.eShopOnContainers.Services.OrderingDb;Trusted_Connection=True;"; - - //SQL SERVER on-premises - //(Integrated Security) - //var connString = @"Server=CESARDLBOOKVHD;Database=Microsoft.eShopOnContainers.Services.OrderingDb;Trusted_Connection=True;"; - - //(SQL Server Authentication) - //var connString = @"Server=10.0.75.1;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"; - + var connString = Configuration["ConnectionString"]; - //(CDLTLL) To use only for EF Migrations - //connString = @"Server=10.0.75.1;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"; - - services.AddDbContext(options => options.UseSqlServer(connString) - .UseSqlServer(connString, b => b.MigrationsAssembly("Ordering.API")) - //(CDLTLL) MigrationsAssembly will be Ordering.SqlData, but when supported - //Standard Library 1.6 by "Microsoft.EntityFrameworkCore.Tools" - //Version "1.0.0-preview2-final" just supports .NET Core - ); + services.AddDbContext(options => + { + options.UseSqlServer(connString) + .UseSqlServer(connString, b => b.MigrationsAssembly("Ordering.API")); + }); services.AddTransient(); services.AddTransient(); @@ -70,9 +63,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); - //if (env.IsDevelopment()) + if (env.IsDevelopment()) + { app.UseDeveloperExceptionPage(); - + } + app.UseMvc(); } } diff --git a/src/Services/Ordering/Ordering.API/project.json b/src/Services/Ordering/Ordering.API/project.json index c330c3657..d5b415b26 100644 --- a/src/Services/Ordering/Ordering.API/project.json +++ b/src/Services/Ordering/Ordering.API/project.json @@ -9,6 +9,7 @@ "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", + "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", "Microsoft.Extensions.Configuration.Json": "1.0.0", "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.Extensions.Logging.Console": "1.0.0",