Skip to content

Commit

Permalink
Merge pull request #34 from Dave-Whiffin/catalog-search
Browse files Browse the repository at this point in the history
Catalog / Product search Issue #19
  • Loading branch information
juanfranblanco authored Feb 29, 2020
2 parents 273fff9 + e49afd8 commit 471a001
Show file tree
Hide file tree
Showing 14 changed files with 67 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Nethereum.eShop.ApplicationCore.Entities;
using Microsoft.EntityFrameworkCore;
using Nethereum.eShop.ApplicationCore.Entities;
using System.Collections.Generic;
using System.Threading.Tasks;

Expand All @@ -13,5 +14,7 @@ public interface IAsyncRepository<T> where T : BaseEntity, IAggregateRoot
Task UpdateAsync(T entity);
Task DeleteAsync(T entity);
Task<int> CountAsync(ISpecification<T> spec);

DbSet<T> DbSet { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Nethereum.eShop.ApplicationCore.Entities;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Nethereum.eShop.ApplicationCore.Interfaces
{
public interface ICatalogItemRepository : IAsyncRepository<CatalogItem>
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ namespace Nethereum.eShop.ApplicationCore.Specifications
{
public class CatalogFilterPaginatedSpecification : BaseSpecification<CatalogItem>
{
public CatalogFilterPaginatedSpecification(int skip, int take, int? brandId, int? typeId)
: base(i => (!brandId.HasValue || i.CatalogBrandId == brandId) &&
(!typeId.HasValue || i.CatalogTypeId == typeId))
public CatalogFilterPaginatedSpecification(int skip, int take, int? brandId, int? typeId, string searchText = null)
: base
(i => (!brandId.HasValue || i.CatalogBrandId == brandId) &&
(!typeId.HasValue || i.CatalogTypeId == typeId) &&
(searchText == null || (i.Name.Contains(searchText) || i.CatalogBrand.Brand.Contains(searchText))))
{
AddInclude(c => c.CatalogBrand);
ApplyOrderBy(c => c.Rank);
ApplyPaging(skip, take);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ namespace Nethereum.eShop.ApplicationCore.Specifications

public class CatalogFilterSpecification : BaseSpecification<CatalogItem>
{
public CatalogFilterSpecification(int? brandId, int? typeId)
public CatalogFilterSpecification(int? brandId, int? typeId, string searchText = null)
: base(i => (!brandId.HasValue || i.CatalogBrandId == brandId) &&
(!typeId.HasValue || i.CatalogTypeId == typeId))
(!typeId.HasValue || i.CatalogTypeId == typeId) &&
(searchText == null || (i.Name.Contains(searchText) || i.CatalogBrand.Brand.Contains(searchText))))
{
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/Nethereum.eShop/Infrastructure/Data/CatalogItemRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Nethereum.eShop.ApplicationCore.Entities;
using Nethereum.eShop.ApplicationCore.Interfaces;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Nethereum.eShop.Infrastructure.Data
{
public class CatalogItemRepository : EfRepository<CatalogItem>, ICatalogItemRepository
{
public CatalogItemRepository(CatalogContext dbContext) : base(dbContext)
{
}
}
}
2 changes: 2 additions & 0 deletions src/Nethereum.eShop/Infrastructure/Data/EfRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class EfRepository<T> : IAsyncRepository<T> where T : BaseEntity, IAggreg
{
protected readonly CatalogContext _dbContext;

public DbSet<T> DbSet => _dbContext.Set<T>();

public EfRepository(CatalogContext dbContext)
{
_dbContext = dbContext;
Expand Down
6 changes: 3 additions & 3 deletions src/Web/Extensions/CacheHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ namespace Nethereum.eShop.Web.Extensions
public static class CacheHelpers
{
public static readonly TimeSpan DefaultCacheDuration = TimeSpan.FromSeconds(30);
private static readonly string _itemsKeyTemplate = "items-{0}-{1}-{2}-{3}";
private static readonly string _itemsKeyTemplate = "items-{0}-{1}-{2}-{3}-{4}";

public static string GenerateCatalogItemCacheKey(int pageIndex, int itemsPage, int? brandId, int? typeId)
public static string GenerateCatalogItemCacheKey(int pageIndex, int itemsPage, int? brandId, int? typeId, string searchText = null)
{
return string.Format(_itemsKeyTemplate, pageIndex, itemsPage, brandId, typeId);
return string.Format(_itemsKeyTemplate, pageIndex, itemsPage, brandId, typeId, searchText);
}

public static string GenerateBrandsCacheKey()
Expand Down
2 changes: 1 addition & 1 deletion src/Web/Interfaces/ICatalogViewModelService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Nethereum.eShop.Web.Services
{
public interface ICatalogViewModelService
{
Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId);
Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId, string searchText = null);
Task<IEnumerable<SelectListItem>> GetBrands();
Task<IEnumerable<SelectListItem>> GetTypes();
}
Expand Down
3 changes: 3 additions & 0 deletions src/Web/Pages/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
<label class="esh-catalog-label" data-title="type">
<select asp-for="@Model.CatalogModel.TypesFilterApplied" asp-items="@Model.CatalogModel.Types" class="esh-catalog-filter"></select>
</label>
<label class="esh-catalog-label" data-title="search">
<input asp-for="@Model.CatalogModel.SearchText" class="esh-catalog-filter" />
</label>
<input class="esh-catalog-send" type="image" src="images/arrow-right.svg" />
</form>
</div>
Expand Down
7 changes: 6 additions & 1 deletion src/Web/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ public IndexModel(ICatalogViewModelService catalogViewModelService)

public async Task OnGet(CatalogIndexViewModel catalogModel, int? pageId)
{
CatalogModel = await _catalogViewModelService.GetCatalogItems(pageId ?? 0, Constants.ITEMS_PER_PAGE, catalogModel.BrandFilterApplied, catalogModel.TypesFilterApplied);
CatalogModel = await _catalogViewModelService.GetCatalogItems(
pageId ?? 0,
Constants.ITEMS_PER_PAGE,
catalogModel.BrandFilterApplied,
catalogModel.TypesFilterApplied,
catalogModel.SearchText);
}
}
}
6 changes: 3 additions & 3 deletions src/Web/Services/CachedCatalogViewModelService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ public async Task<IEnumerable<SelectListItem>> GetBrands()
});
}

public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId)
public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId, string searchText = null)
{
var cacheKey = CacheHelpers.GenerateCatalogItemCacheKey(pageIndex, Constants.ITEMS_PER_PAGE, brandId, typeId);
var cacheKey = CacheHelpers.GenerateCatalogItemCacheKey(pageIndex, Constants.ITEMS_PER_PAGE, brandId, typeId, searchText);

return await _cache.GetOrCreateAsync(cacheKey, async entry =>
{
entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration;
return await _catalogViewModelService.GetCatalogItems(pageIndex, itemsPage, brandId, typeId);
return await _catalogViewModelService.GetCatalogItems(pageIndex, itemsPage, brandId, typeId, searchText);
});
}

Expand Down
12 changes: 6 additions & 6 deletions src/Web/Services/CatalogViewModelService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Nethereum.eShop.ApplicationCore.Entities;
using Nethereum.eShop.ApplicationCore.Interfaces;
using Nethereum.eShop.ApplicationCore.Specifications;
using Nethereum.eShop.Web.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -18,14 +18,14 @@ namespace Nethereum.eShop.Web.Services
public class CatalogViewModelService : ICatalogViewModelService
{
private readonly ILogger<CatalogViewModelService> _logger;
private readonly IAsyncRepository<CatalogItem> _itemRepository;
private readonly ICatalogItemRepository _itemRepository;
private readonly IAsyncRepository<CatalogBrand> _brandRepository;
private readonly IAsyncRepository<CatalogType> _typeRepository;
private readonly IUriComposer _uriComposer;

public CatalogViewModelService(
ILoggerFactory loggerFactory,
IAsyncRepository<CatalogItem> itemRepository,
ICatalogItemRepository itemRepository,
IAsyncRepository<CatalogBrand> brandRepository,
IAsyncRepository<CatalogType> typeRepository,
IUriComposer uriComposer)
Expand All @@ -37,13 +37,13 @@ public CatalogViewModelService(
_uriComposer = uriComposer;
}

public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId)
public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId, string searchText = null)
{
_logger.LogInformation("GetCatalogItems called.");

var filterSpecification = new CatalogFilterSpecification(brandId, typeId);
var filterSpecification = new CatalogFilterSpecification(brandId, typeId, searchText);
var filterPaginatedSpecification =
new CatalogFilterPaginatedSpecification(itemsPage * pageIndex, itemsPage, brandId, typeId);
new CatalogFilterPaginatedSpecification(itemsPage * pageIndex, itemsPage, brandId, typeId, searchText);

// the implementation below using ForEach and Count. We need a List.
var itemsOnPage = await _itemRepository.ListAsync(filterPaginatedSpecification);
Expand Down
1 change: 1 addition & 0 deletions src/Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddMediatR(typeof(BasketViewModelService).Assembly);

services.AddScoped(typeof(IAsyncRepository<>), typeof(EfRepository<>));
services.AddScoped<ICatalogItemRepository, CatalogItemRepository>();
services.AddScoped<ICatalogViewModelService, CachedCatalogViewModelService>();
services.AddScoped<IBasketService, BasketService>();
services.AddScoped<IBasketViewModelService, BasketViewModelService>();
Expand Down
2 changes: 2 additions & 0 deletions src/Web/ViewModels/CatalogIndexViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class CatalogIndexViewModel
public IEnumerable<SelectListItem> Types { get; set; }
public int? BrandFilterApplied { get; set; }
public int? TypesFilterApplied { get; set; }

public string SearchText { get; set; }
public PaginationInfoViewModel PaginationInfo { get; set; }
}
}

0 comments on commit 471a001

Please sign in to comment.