catalog integration with real service in Spa web application (pagination, brand & type filter, etc.).
This commit is contained in:
parent
a73be10615
commit
141a9a2246
@ -15,7 +15,6 @@ import { CatalogModule } from './catalog/catalog.module';
|
||||
imports: [
|
||||
BrowserModule,
|
||||
routing,
|
||||
// FormsModule,
|
||||
HttpModule,
|
||||
// Only module that app module loads
|
||||
SharedModule.forRoot(),
|
||||
|
@ -7,36 +7,21 @@
|
||||
<div class="catalog-filter">
|
||||
<div class="catalog-filter-container">
|
||||
<div class="container">
|
||||
<select>
|
||||
<option>Opción 1</option>
|
||||
<option>Opción 2</option>
|
||||
<select (change)="onBrandFilterChanged($event, $event.target.value)">
|
||||
<option *ngFor="let brand of brands" [value]="brand.id">{{brand.brand}}</option>
|
||||
</select>
|
||||
<select>
|
||||
<option>Opción 1</option>
|
||||
<option>Opción 2</option>
|
||||
<select (change)="onTypeFilterChanged($event, $event.target.value)">
|
||||
<option *ngFor="let type of types" [value]="type.id">{{type.type}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="" (click)="onFilterApplied($event)">Apply</button>
|
||||
</div>
|
||||
</div>
|
||||
<esh-pager [model]="paginationInfo" (changed)="onPageChanged($event)"></esh-pager>
|
||||
<div class="catalog-content row">
|
||||
<div class="col-md-4 catalog-content-item">
|
||||
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt"/>
|
||||
<div class="col-md-4 catalog-content-item" *ngFor="let item of catalog?.data">
|
||||
<img src="{{item.pictureUri}}"/>
|
||||
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||
</div>
|
||||
<div class="col-md-4 catalog-content-item">
|
||||
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||
</div>
|
||||
<div class="col-md-4 catalog-content-item">
|
||||
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||
</div>
|
||||
<div class="col-md-4 catalog-content-item">
|
||||
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||
</div>
|
||||
<div class="col-md-4 catalog-content-item">
|
||||
<img src="https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt" />
|
||||
<button class="catalog-content-item-button">[ ADD TO CART ]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<esh-pager [model]="paginationInfo" (changed)="onPageChanged($event)"></esh-pager>
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
})
|
||||
|
@ -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<ICatalog> {
|
||||
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<ICatalogBrand[]> {
|
||||
return this.service.get(this.brandUrl).map((response: Response) => {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
getTypes(): Observable<ICatalogType[]> {
|
||||
return this.service.get(this.typesUrl).map((response: Response) => {
|
||||
return response.json();
|
||||
});
|
||||
};
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<nav>
|
||||
<ul>
|
||||
<li class="page-item">
|
||||
<span class="text previous" id="Previous"
|
||||
(click)="onPreviousCliked($event)"
|
||||
aria-label="Previous">
|
||||
Previous
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="col-xs-4 u-align-center"><span>Showing {{model?.itemsPage}} of {{model?.totalItems}} products - Page {{model?.actualPage}} - {{model?.totalPages}}</span></div>
|
||||
<div class="col-xs-4">
|
||||
<nav>
|
||||
<ul>
|
||||
<li class="page-item">
|
||||
<span class="text next" id="Next"
|
||||
(click)="onNextClicked($event)"
|
||||
aria-label="Next">
|
||||
Next
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
@ -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<number> = new EventEmitter<number>();
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
export interface ICatalogBrand {
|
||||
id: number
|
||||
brand: string
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
export interface ICatalogType {
|
||||
id: number
|
||||
type: string
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export class OperationResult {
|
||||
constructor(public succeeded: boolean, public message: string) { }
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export interface IPager {
|
||||
itemsPage: number,
|
||||
totalItems: number,
|
||||
actualPage: number,
|
||||
totalPages: number
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export class User {
|
||||
constructor(public displayName: string, public roles: string[]) {
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Response> {
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user