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",