@ -0,0 +1,24 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Marketing.API.ViewModel | |||||
{ | |||||
using System.Collections.Generic; | |||||
public class PaginatedItemsViewModel<TEntity> where TEntity : class | |||||
{ | |||||
public int PageIndex { get; private set; } | |||||
public int PageSize { get; private set; } | |||||
public long Count { get; private set; } | |||||
public IEnumerable<TEntity> Data { get; private set; } | |||||
public PaginatedItemsViewModel(int pageIndex, int pageSize, long count, IEnumerable<TEntity> data) | |||||
{ | |||||
this.PageIndex = pageIndex; | |||||
this.PageSize = pageSize; | |||||
this.Count = count; | |||||
this.Data = data; | |||||
} | |||||
} | |||||
} |
@ -1 +0,0 @@ | |||||
|
@ -1,89 +0,0 @@ | |||||
import { Injectable } from '@angular/core'; | |||||
import { Response } from '@angular/http'; | |||||
import { DataService } from '../shared/services/data.service'; | |||||
import { IOrder } from '../shared/models/order.model'; | |||||
import { IOrderItem } from '../shared/models/orderItem.model'; | |||||
import { IOrderDetail } from "../shared/models/order-detail.model"; | |||||
import { SecurityService } from '../shared/services/security.service'; | |||||
import { ConfigurationService } from '../shared/services/configuration.service'; | |||||
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 CampaignService { | |||||
private marketingUrl: string = ''; | |||||
constructor(private service: DataService, private identityService: SecurityService, private configurationService: ConfigurationService) { | |||||
if (this.configurationService.isReady) | |||||
this.marketingUrl = this.configurationService.serverSettings.marketingUrl; | |||||
else | |||||
this.configurationService.settingsLoaded$.subscribe(x => this.marketingUrl = this.configurationService.serverSettings.marketingUrl); | |||||
} | |||||
getOrders(): Observable<IOrder[]> { | |||||
let url = this.marketingUrl + '/api/v1/campaigns/'; | |||||
return this.service.get(url).map((response: Response) => { | |||||
return response.json(); | |||||
}); | |||||
} | |||||
getOrder(id: number): Observable<IOrderDetail> { | |||||
let url = this.marketingUrl + '/api/v1/campaigns/' + id; | |||||
return this.service.get(url).map((response: Response) => { | |||||
return response.json(); | |||||
}); | |||||
} | |||||
mapOrderAndIdentityInfoNewOrder(): IOrder { | |||||
let order = <IOrder>{}; | |||||
let basket = this.basketService.basket; | |||||
let identityInfo = this.identityService.UserData; | |||||
console.log(basket); | |||||
console.log(identityInfo); | |||||
// Identity data mapping: | |||||
order.street = identityInfo.address_street; | |||||
order.city = identityInfo.address_city; | |||||
order.country = identityInfo.address_country; | |||||
order.state = identityInfo.address_state; | |||||
order.zipcode = identityInfo.address_zip_code; | |||||
order.cardexpiration = identityInfo.card_expiration; | |||||
order.cardnumber = identityInfo.card_number; | |||||
order.cardsecuritynumber = identityInfo.card_security_number; | |||||
order.cardtypeid = identityInfo.card_type; | |||||
order.cardholdername = identityInfo.card_holder; | |||||
order.total = 0; | |||||
order.expiration = identityInfo.card_expiration; | |||||
// basket data mapping: | |||||
order.orderItems = new Array<IOrderItem>(); | |||||
basket.items.forEach(x => { | |||||
let item: IOrderItem = <IOrderItem>{}; | |||||
item.pictureurl = x.pictureUrl; | |||||
item.productId = +x.productId; | |||||
item.productname = x.productName; | |||||
item.unitprice = x.unitPrice; | |||||
item.units = x.quantity; | |||||
order.total += (item.unitprice * item.units); | |||||
order.orderItems.push(item); | |||||
}); | |||||
order.buyer = basket.buyerId; | |||||
return order; | |||||
} | |||||
} | |||||
@ -0,0 +1,17 @@ | |||||
<esh-header url="/campaigns">Back to campaigns</esh-header> | |||||
<div class="container"> | |||||
<div class="esh-campaign_detail"> | |||||
<div class="card esh-campaigns-items"> | |||||
<img class="card-img-top" src="{{campaign.pictureUri}}" alt="{{campaign.name}}"> | |||||
<div class="card-block"> | |||||
<h4 class="card-title">{{campaign.name}}</h4> | |||||
<p class="card-text">{{campaign.description}}</p> | |||||
<p class="card-text"> | |||||
<small class="text-muted"> | |||||
From {{campaign.from | date}} Until {{campaign.to | date}} | |||||
</small> | |||||
</p> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> |
@ -0,0 +1,57 @@ | |||||
@import '../../variables'; | |||||
.esh-campaign_detail { | |||||
min-height: 80vh; | |||||
margin-top: 1rem; | |||||
&-section { | |||||
padding: 1rem 0; | |||||
&--right { | |||||
text-align: right; | |||||
} | |||||
} | |||||
&-titles { | |||||
padding-bottom: 1rem; | |||||
padding-top: 2rem; | |||||
} | |||||
&-title { | |||||
text-transform: uppercase; | |||||
} | |||||
&-items { | |||||
&--border { | |||||
border-bottom: $border-light solid $color-foreground-bright; | |||||
padding: .5rem 0; | |||||
&:last-of-type { | |||||
border-color: transparent; | |||||
} | |||||
} | |||||
} | |||||
$item-height: 8rem; | |||||
&-item { | |||||
font-size: $font-size-m; | |||||
font-weight: $font-weight-semilight; | |||||
&--middle { | |||||
line-height: $item-height; | |||||
@media screen and (max-width: $media-screen-s) { | |||||
line-height: $font-size-m; | |||||
} | |||||
} | |||||
&--mark { | |||||
color: $color-secondary; | |||||
} | |||||
} | |||||
&-image { | |||||
height: $item-height; | |||||
} | |||||
} |
@ -0,0 +1,30 @@ | |||||
import { Component, OnInit } from '@angular/core'; | |||||
import { CampaignsService } from '../campaigns.service'; | |||||
import { ICampaignItem } from '../../shared/models/campaignItem.model'; | |||||
import { ActivatedRoute } from '@angular/router'; | |||||
@Component({ | |||||
selector: 'esh-campaigns_detail', | |||||
styleUrls: ['./campaigns-detail.component.scss'], | |||||
templateUrl: './campaigns-detail.component.html' | |||||
}) | |||||
export class CampaignsDetailComponent implements OnInit { | |||||
public campaign: ICampaignItem = <ICampaignItem>{}; | |||||
constructor(private service: CampaignsService, private route: ActivatedRoute) { } | |||||
ngOnInit() { | |||||
this.route.params.subscribe(params => { | |||||
let id = +params['id']; // (+) converts string 'id' to a number | |||||
this.getCampaign(id); | |||||
}); | |||||
} | |||||
getCampaign(id: number) { | |||||
this.service.getCampaign(id).subscribe(campaign => { | |||||
this.campaign = campaign; | |||||
console.log('campaign retrieved: ' + campaign.id); | |||||
console.log(this.campaign); | |||||
}); | |||||
} | |||||
} |
@ -0,0 +1,30 @@ | |||||
<esh-header url="/catalog">Back to catalog</esh-header> | |||||
<div class="container"> | |||||
<div *ngIf="campaigns?.data?.length > 0"> | |||||
<esh-pager [model]="paginationInfo" (changed)="onPageChanged($event)"></esh-pager> | |||||
<div class="card-group esh-campaign-items row"> | |||||
<div class="esh-campaign-item col-md-4" | |||||
*ngFor="let item of campaigns.data"> | |||||
<div class="card-block"> | |||||
<h4 class="card-title esh-campaigns-name">{{item.name}}</h4> | |||||
<img class="card-img-top esh-campaigns-thumbnail" src="{{item.pictureUri}}" alt="{{item.name}}"> | |||||
<input [ngClass]="{'esh-campaign-button': true}" type="submit" value="More details" routerLink="/campaigns/{{item.id}}"> | |||||
</div> | |||||
<div class="card-footer"> | |||||
<small class="text-muted"> | |||||
From {{item.from | date }} To {{item.to | date }} | |||||
</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<esh-pager [model]="paginationInfo" (changed)="onPageChanged($event)"></esh-pager> | |||||
</div> | |||||
<div *ngIf="campaigns?.data?.length == 0"> | |||||
<span>THERE ARE NO RESULTS THAT MATCH YOUR SEARCH</span> | |||||
</div> | |||||
</div> | |||||
@ -0,0 +1,65 @@ | |||||
@import '../variables'; | |||||
.esh-campaign { | |||||
$banner-height: 260px; | |||||
&-title { | |||||
position: relative; | |||||
top: $banner-height / 3.5; | |||||
} | |||||
&-items { | |||||
margin-top: 1rem; | |||||
} | |||||
&-item { | |||||
margin-bottom: 1.5rem; | |||||
text-align: center; | |||||
width: 33%; | |||||
display: inline-block; | |||||
float: none !important; | |||||
@media screen and (max-width: $media-screen-m) { | |||||
width: 50%; | |||||
} | |||||
@media screen and (max-width: $media-screen-s) { | |||||
width: 100%; | |||||
} | |||||
} | |||||
&-thumbnail { | |||||
max-width: 370px; | |||||
width: 100%; | |||||
} | |||||
&-button { | |||||
background-color: $color-secondary; | |||||
border: 0; | |||||
color: $color-foreground-brighter; | |||||
cursor: pointer; | |||||
font-size: $font-size-m; | |||||
height: 3rem; | |||||
margin-top: 1rem; | |||||
transition: all $animation-speed-default; | |||||
width: 80%; | |||||
&.is-disabled { | |||||
opacity: .5; | |||||
pointer-events: none; | |||||
} | |||||
&:hover { | |||||
background-color: $color-secondary-darker; | |||||
transition: all $animation-speed-default; | |||||
} | |||||
} | |||||
&-name { | |||||
font-size: $font-size-m; | |||||
font-weight: $font-weight-semilight; | |||||
margin-top: .5rem; | |||||
text-align: center; | |||||
text-transform: uppercase; | |||||
} | |||||
} |
@ -0,0 +1,49 @@ | |||||
import { Component, OnInit } from '@angular/core'; | |||||
import { CampaignsService } from './campaigns.service'; | |||||
import { ICampaign } from '../shared/models/campaign.model'; | |||||
import { IPager } from '../shared/models/pager.model'; | |||||
import { ConfigurationService } from '../shared/services/configuration.service'; | |||||
@Component({ | |||||
selector: 'esh-campaigns', | |||||
styleUrls: ['./campaigns.component.scss'], | |||||
templateUrl: './campaigns.component.html' | |||||
}) | |||||
export class CampaignsComponent implements OnInit { | |||||
private interval = null; | |||||
paginationInfo: IPager; | |||||
campaigns: ICampaign; | |||||
constructor(private service: CampaignsService, private configurationService: ConfigurationService) { } | |||||
ngOnInit() { | |||||
if (this.configurationService.isReady) { | |||||
this.getCampaigns(9, 0) | |||||
} else { | |||||
this.configurationService.settingsLoaded$.subscribe(x => { | |||||
this.getCampaigns(9, 0); | |||||
}); | |||||
} | |||||
} | |||||
onPageChanged(value: any) { | |||||
console.log('campaigns pager event fired' + value); | |||||
//event.preventDefault(); | |||||
this.paginationInfo.actualPage = value; | |||||
this.getCampaigns(this.paginationInfo.itemsPage, value); | |||||
} | |||||
getCampaigns(pageSize: number, pageIndex: number) { | |||||
this.service.getCampaigns(pageIndex, pageSize).subscribe(campaigns => { | |||||
this.campaigns = campaigns; | |||||
this.paginationInfo = { | |||||
actualPage : campaigns.pageIndex, | |||||
itemsPage : campaigns.pageSize, | |||||
totalItems : campaigns.count, | |||||
totalPages: Math.ceil(campaigns.count / campaigns.pageSize), | |||||
items: campaigns.pageSize | |||||
}; | |||||
}); | |||||
} | |||||
} | |||||
@ -0,0 +1,15 @@ | |||||
import { NgModule } from '@angular/core'; | |||||
import { BrowserModule } from '@angular/platform-browser'; | |||||
import { SharedModule } from '../shared/shared.module'; | |||||
import { CampaignsComponent } from './campaigns.component'; | |||||
import { CampaignsDetailComponent } from './campaigns-detail/campaigns-detail.component'; | |||||
import { CampaignsService } from './campaigns.service'; | |||||
import { Header } from '../shared/components/header/header'; | |||||
@NgModule({ | |||||
imports: [BrowserModule, SharedModule], | |||||
declarations: [CampaignsComponent, CampaignsDetailComponent], | |||||
providers: [CampaignsService] | |||||
}) | |||||
export class CampaignsModule { } |
@ -0,0 +1,52 @@ | |||||
import { Injectable } from '@angular/core'; | |||||
import { Response } from '@angular/http'; | |||||
import { DataService } from '../shared/services/data.service'; | |||||
import { ICampaign } from '../shared/models/campaign.model'; | |||||
import { ICampaignItem } from '../shared/models/campaignItem.model'; | |||||
import { SecurityService } from '../shared/services/security.service'; | |||||
import { ConfigurationService } from '../shared/services/configuration.service'; | |||||
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 CampaignsService { | |||||
private marketingUrl: string = ''; | |||||
private buyerId: string = ''; | |||||
constructor(private service: DataService, private identityService: SecurityService, private configurationService: ConfigurationService) { | |||||
if (this.identityService.IsAuthorized) { | |||||
if (this.identityService.UserData) { | |||||
this.buyerId = this.identityService.UserData.sub; | |||||
} | |||||
} | |||||
if (this.configurationService.isReady) | |||||
this.marketingUrl = this.configurationService.serverSettings.marketingUrl; | |||||
else | |||||
this.configurationService.settingsLoaded$.subscribe(x => this.marketingUrl = this.configurationService.serverSettings.marketingUrl); | |||||
} | |||||
getCampaigns(pageIndex: number, pageSize: number): Observable<ICampaign> { | |||||
let url = this.marketingUrl + '/api/v1/campaigns/user/' + this.buyerId; | |||||
url = url + '?pageIndex=' + pageIndex + '&pageSize=' + pageSize; | |||||
return this.service.get(url).map((response: Response) => { | |||||
return response.json(); | |||||
}); | |||||
} | |||||
getCampaign(id: number): Observable<ICampaignItem> { | |||||
let url = this.marketingUrl + '/api/v1/campaigns/' + id; | |||||
return this.service.get(url).map((response: Response) => { | |||||
return response.json(); | |||||
}); | |||||
} | |||||
} | |||||
@ -0,0 +1,9 @@ | |||||
import {ICampaignItem} from './campaignItem.model'; | |||||
export interface ICampaign { | |||||
data: ICampaignItem[]; | |||||
pageIndex: number; | |||||
pageSize: number; | |||||
count: number; | |||||
} | |||||
@ -0,0 +1,8 @@ | |||||
export interface ICampaignItem { | |||||
id: number; | |||||
name: string; | |||||
description: string; | |||||
from: Date; | |||||
to: Date; | |||||
pictureUri: string; | |||||
} |