Updating SPA for working with PurchaseBFF.
This commit is contained in:
parent
735e9bd94e
commit
8edd736196
@ -112,12 +112,10 @@ services:
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||
- CatalogUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5101
|
||||
- OrderingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102
|
||||
- IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||
- BasketUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103
|
||||
- MarketingUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5110
|
||||
- LocationsUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5109
|
||||
- PurchaseUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5200
|
||||
- CatalogUrlHC=http://catalog.api/hc
|
||||
- OrderingUrlHC=http://ordering.api/hc
|
||||
- IdentityUrlHC=http://identity.api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser.
|
||||
|
@ -29,6 +29,15 @@ namespace OcelotApiGw
|
||||
var identityUrl = _cfg.GetValue<string>("IdentityUrl");
|
||||
var authenticationProviderKey = "IdentityApiKey";
|
||||
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy",
|
||||
builder => builder.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials());
|
||||
});
|
||||
|
||||
services.AddAuthentication()
|
||||
.AddJwtBearer(authenticationProviderKey, x =>
|
||||
{
|
||||
@ -68,6 +77,8 @@ namespace OcelotApiGw
|
||||
|
||||
loggerFactory.AddConsole(_cfg.GetSection("Logging"));
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
app.UseOcelot().Wait();
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ namespace PurchaseBff.Config
|
||||
public class CatalogOperations
|
||||
{
|
||||
public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}";
|
||||
public static string GetItemsById(IEnumerable<int> ids) => $"/api/v1/catalog/items?ids={string.Join(',', ids)}";
|
||||
}
|
||||
|
||||
public class BasketOperations
|
||||
|
@ -21,6 +21,49 @@ namespace PurchaseBff.Controllers
|
||||
_basket = basketService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> UpdateAllBasket([FromBody] UpdateBasketRequest data)
|
||||
{
|
||||
|
||||
if (data.Items == null || !data.Items.Any())
|
||||
{
|
||||
return BadRequest("Need to pass at least one basket line");
|
||||
}
|
||||
|
||||
// Retrieve the current basket
|
||||
var currentBasket = await _basket.GetById(data.BuyerId);
|
||||
if (currentBasket == null)
|
||||
{
|
||||
currentBasket = new BasketData(data.BuyerId);
|
||||
}
|
||||
|
||||
var catalogItems = await _catalog.GetCatalogItems(data.Items.Select(x => x.ProductId));
|
||||
var newBasket = new BasketData(data.BuyerId);
|
||||
|
||||
foreach (var bitem in data.Items)
|
||||
{
|
||||
var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId);
|
||||
if (catalogItem == null)
|
||||
{
|
||||
return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})");
|
||||
}
|
||||
|
||||
newBasket.Items.Add(new BasketDataItem()
|
||||
{
|
||||
Id = bitem.Id,
|
||||
ProductId = catalogItem.Id.ToString(),
|
||||
ProductName = catalogItem.Name,
|
||||
PictureUrl = catalogItem.PictureUri,
|
||||
UnitPrice = catalogItem.Price,
|
||||
Quantity = bitem.Quantity
|
||||
});
|
||||
}
|
||||
|
||||
await _basket.Update(newBasket);
|
||||
return Ok(newBasket);
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Route("items")]
|
||||
public async Task<IActionResult> UpdateQuantities([FromBody] UpdateBasketItemsRequest data)
|
||||
|
21
src/BFFs/PurchaseBff/Models/UpdateBasketRequest.cs
Normal file
21
src/BFFs/PurchaseBff/Models/UpdateBasketRequest.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PurchaseBff.Models
|
||||
{
|
||||
public class UpdateBasketRequest
|
||||
{
|
||||
public string BuyerId { get; set; }
|
||||
|
||||
public IEnumerable<UpdateBasketRequestItemData> Items { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateBasketRequestItemData
|
||||
{
|
||||
public string Id { get; set; } // Basket id
|
||||
public int ProductId { get; set; } // Catalog item id
|
||||
public int Quantity { get; set; } // Quantity
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:58243/",
|
||||
"applicationUrl": "http://localhost:57425/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
|
@ -31,5 +31,13 @@ namespace PurchaseBff.Services
|
||||
var item = JsonConvert.DeserializeObject<CatalogItem>(data);
|
||||
return item;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<CatalogItem>> GetCatalogItems(IEnumerable<int> ids)
|
||||
{
|
||||
var data = await _apiClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemsById(ids));
|
||||
var item = JsonConvert.DeserializeObject<CatalogItem[]>(data);
|
||||
return item;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,5 +9,6 @@ namespace PurchaseBff.Services
|
||||
public interface ICatalogService
|
||||
{
|
||||
Task<CatalogItem> GetCatalogItem(int id);
|
||||
Task<IEnumerable<CatalogItem>> GetCatalogItems(IEnumerable<int> ids);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:50920/",
|
||||
"applicationUrl": "http://localhost:57423/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
|
@ -32,11 +32,16 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
||||
|
||||
// GET api/v1/[controller]/items[?pageSize=3&pageIndex=10]
|
||||
[HttpGet]
|
||||
[Route("[action]")]
|
||||
[Route("items")]
|
||||
[ProducesResponseType(typeof(PaginatedItemsViewModel<CatalogItem>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
|
||||
|
||||
[ProducesResponseType(typeof(IEnumerable<CatalogItem>), (int)HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> Items([FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0, [FromQuery] string ids = null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ids))
|
||||
{
|
||||
return GetItemsByIds(ids);
|
||||
}
|
||||
|
||||
var totalItems = await _catalogContext.CatalogItems
|
||||
.LongCountAsync();
|
||||
|
||||
@ -54,6 +59,23 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers
|
||||
return Ok(model);
|
||||
}
|
||||
|
||||
private IActionResult GetItemsByIds(string ids)
|
||||
{
|
||||
var numIds = ids.Split(',')
|
||||
.Select(id => (Ok: int.TryParse(id, out int x), Value: x));
|
||||
if (!numIds.All(nid => nid.Ok))
|
||||
{
|
||||
return BadRequest("ids value invalid. Must be comma-separated list of numbers");
|
||||
}
|
||||
|
||||
var idsToSelect = numIds.Select(id => id.Value);
|
||||
var items = _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToList();
|
||||
|
||||
items = ChangeUriPlaceholder(items);
|
||||
return Ok(items);
|
||||
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("items/{id:int}")]
|
||||
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
||||
|
@ -3,7 +3,7 @@
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:57623/",
|
||||
"applicationUrl": "http://localhost:57424/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
|
@ -7,13 +7,13 @@ namespace eShopOnContainers.WebSPA
|
||||
{
|
||||
public class AppSettings
|
||||
{
|
||||
public string BaseUrl { get; set; }
|
||||
public string CatalogUrl { get; set; }
|
||||
public string OrderingUrl { get; set; }
|
||||
public string IdentityUrl { get; set; }
|
||||
public string BasketUrl { get; set; }
|
||||
public string MarketingUrl { get; set; }
|
||||
|
||||
public string PurchaseUrl { get; set; }
|
||||
|
||||
public string ActivateCampaignDetailFunction { get; set; }
|
||||
public bool UseCustomizationData { get; set; }
|
||||
public bool UseCustomizationData { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import { Subject } from 'rxjs/Subject';
|
||||
@Injectable()
|
||||
export class BasketService {
|
||||
private basketUrl: string = '';
|
||||
private purchaseUrl: string = '';
|
||||
basket: IBasket = {
|
||||
buyerId: '',
|
||||
items: []
|
||||
@ -40,12 +41,14 @@ export class BasketService {
|
||||
if (this.authService.UserData) {
|
||||
this.basket.buyerId = this.authService.UserData.sub;
|
||||
if (this.configurationService.isReady) {
|
||||
this.basketUrl = this.configurationService.serverSettings.basketUrl;
|
||||
this.basketUrl = this.configurationService.serverSettings.purchaseUrl;
|
||||
this.purchaseUrl = this.configurationService.serverSettings.purchaseUrl;
|
||||
this.loadData();
|
||||
}
|
||||
else {
|
||||
this.configurationService.settingsLoaded$.subscribe(x => {
|
||||
this.basketUrl = this.configurationService.serverSettings.basketUrl;
|
||||
this.basketUrl = this.configurationService.serverSettings.purchaseUrl;
|
||||
this.purchaseUrl = this.configurationService.serverSettings.purchaseUrl;
|
||||
this.loadData();
|
||||
});
|
||||
}
|
||||
@ -63,7 +66,7 @@ export class BasketService {
|
||||
}
|
||||
|
||||
setBasket(basket): Observable<boolean> {
|
||||
let url = this.basketUrl + '/api/v1/basket/';
|
||||
let url = this.purchaseUrl + '/purchase-bff/api/v1/basket/';
|
||||
this.basket = basket;
|
||||
return this.service.post(url, basket).map((response: Response) => {
|
||||
return true;
|
||||
@ -71,7 +74,7 @@ export class BasketService {
|
||||
}
|
||||
|
||||
setBasketCheckout(basketCheckout): Observable<boolean> {
|
||||
let url = this.basketUrl + '/api/v1/basket/checkout';
|
||||
let url = this.basketUrl + '/purchase-bff/api/v1/b/basket/checkout';
|
||||
return this.service.postWithId(url, basketCheckout).map((response: Response) => {
|
||||
this.basketEvents.orderCreated();
|
||||
return true;
|
||||
@ -79,7 +82,7 @@ export class BasketService {
|
||||
}
|
||||
|
||||
getBasket(): Observable<IBasket> {
|
||||
let url = this.basketUrl + '/api/v1/basket/' + this.basket.buyerId;
|
||||
let url = this.basketUrl + '/api/v1/b/basket/' + this.basket.buyerId;
|
||||
return this.service.get(url).map((response: Response) => {
|
||||
if (response.status === 204) {
|
||||
return null;
|
||||
|
@ -21,9 +21,9 @@ export class CatalogService {
|
||||
|
||||
constructor(private service: DataService, private configurationService: ConfigurationService) {
|
||||
this.configurationService.settingsLoaded$.subscribe(x => {
|
||||
this.catalogUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/items';
|
||||
this.brandUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/catalogbrands';
|
||||
this.typesUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/catalogtypes';
|
||||
this.catalogUrl = this.configurationService.serverSettings.purchaseUrl + '/purchase-bff/api/v1/c/catalog/items';
|
||||
this.brandUrl = this.configurationService.serverSettings.purchaseUrl + '/purchase-bff/api/v1/c/catalog/catalogbrands';
|
||||
this.typesUrl = this.configurationService.serverSettings.purchaseUrl + '/purchase-bff/api/v1/c/catalog/catalogtypes';
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -22,14 +22,14 @@ export class OrdersService {
|
||||
|
||||
constructor(private service: DataService, private basketService: BasketWrapperService, private identityService: SecurityService, private configurationService: ConfigurationService) {
|
||||
if (this.configurationService.isReady)
|
||||
this.ordersUrl = this.configurationService.serverSettings.orderingUrl;
|
||||
this.ordersUrl = this.configurationService.serverSettings.purchaseUrl;
|
||||
else
|
||||
this.configurationService.settingsLoaded$.subscribe(x => this.ordersUrl = this.configurationService.serverSettings.orderingUrl);
|
||||
this.configurationService.settingsLoaded$.subscribe(x => this.ordersUrl = this.configurationService.serverSettings.purchaseUrl);
|
||||
|
||||
}
|
||||
|
||||
getOrders(): Observable<IOrder[]> {
|
||||
let url = this.ordersUrl + '/api/v1/orders';
|
||||
let url = this.ordersUrl + '/purchase-bff/api/v1/o/orders';
|
||||
|
||||
return this.service.get(url).map((response: Response) => {
|
||||
return response.json();
|
||||
@ -37,7 +37,7 @@ export class OrdersService {
|
||||
}
|
||||
|
||||
getOrder(id: number): Observable<IOrderDetail> {
|
||||
let url = this.ordersUrl + '/api/v1/orders/' + id;
|
||||
let url = this.ordersUrl + '/purchase-bff/api/v1/o/orders/' + id;
|
||||
|
||||
return this.service.get(url).map((response: Response) => {
|
||||
return response.json();
|
||||
|
@ -1,8 +1,6 @@
|
||||
export interface IConfiguration {
|
||||
catalogUrl: string,
|
||||
orderingUrl: string,
|
||||
identityUrl: string,
|
||||
basketUrl: string,
|
||||
marketingUrl: string,
|
||||
purchaseUrl: string,
|
||||
activateCampaignDetailFunction: boolean
|
||||
}
|
@ -28,11 +28,9 @@ export class ConfigurationService {
|
||||
console.log('server settings loaded');
|
||||
this.serverSettings = response.json();
|
||||
console.log(this.serverSettings);
|
||||
this.storageService.store('basketUrl', this.serverSettings.basketUrl);
|
||||
this.storageService.store('catalogUrl', this.serverSettings.catalogUrl);
|
||||
this.storageService.store('identityUrl', this.serverSettings.identityUrl);
|
||||
this.storageService.store('orderingUrl', this.serverSettings.orderingUrl);
|
||||
this.storageService.store('marketingUrl', this.serverSettings.marketingUrl);
|
||||
this.storageService.store('purchaseUrl', this.serverSettings.purchaseUrl);
|
||||
this.storageService.store('activateCampaignDetailFunction', this.serverSettings.activateCampaignDetailFunction);
|
||||
this.isReady = true;
|
||||
this.settingsLoadedSource.next();
|
||||
|
@ -82,7 +82,7 @@ export class SecurityService {
|
||||
let client_id = 'js';
|
||||
let redirect_uri = location.origin + '/';
|
||||
let response_type = 'id_token token';
|
||||
let scope = 'openid profile orders basket marketing locations';
|
||||
let scope = 'openid profile orders basket marketing locations purchasebff';
|
||||
let nonce = 'N' + Math.random() + '' + Date.now();
|
||||
let state = Date.now() + '' + Math.random();
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:50921/",
|
||||
"applicationUrl": "http://localhost:64923/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
|
@ -1,10 +1,8 @@
|
||||
{
|
||||
"CatalogUrl": "http://localhost:5101",
|
||||
"OrderingUrl": "http://localhost:5102",
|
||||
"BasketUrl": "http://localhost:5103",
|
||||
"IdentityUrl": "http://localhost:5105",
|
||||
"MarketingUrl": "http://localhost:5110",
|
||||
"CallBackUrl": "http://localhost:5104/",
|
||||
"PurchaseUrl": "http://localhost:5200",
|
||||
"UseCustomizationData": true,
|
||||
"IsClusterEnv": "False",
|
||||
"ActivateCampaignDetailFunction": true,
|
||||
|
Loading…
x
Reference in New Issue
Block a user