Commit 6c248099 authored by TTrueBenji's avatar TTrueBenji

Добавить сортировку пользователей.

***
- Добавил сервис для сортировки пользователей по имени и возрасту.
- Добавил сервис для поиска пользователей по имени.
- Добавил сервис для постраничной навигации по списку пользователей.
***
parent 26b5aa62
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using PhoneStore.Models;
using PhoneStore.ViewModels;
using PhoneStore.Services.Abstractions;
using Order = PhoneStore.Enums.Order;
namespace PhoneStore.Controllers
{
public class UsersController : Controller
{
private readonly MobileContext _db;
private readonly IUserService _userService;
public UsersController(MobileContext db)
public UsersController(IUserService userService)
{
_db = db;
_userService = userService;
}
[HttpGet]
public IActionResult Index(
string filteringCriterionByName,
int page = 1,
Order order = Order.NameAsc)
public async Task<IActionResult> Index(string filterByName, Order order = Order.AgeAsc, int page = 1)
{
int pageSize = 2;
IQueryable<User> users = _db.Users.AsQueryable();
if (!string.IsNullOrEmpty(filteringCriterionByName))
users = users.Where(u => u.Name.Contains(filteringCriterionByName));
int count = users.Count();
users = _db
.Users
.OrderBy(u => u.Name)
.Skip((page - 1) * pageSize)
.Take(pageSize);
ViewBag.NameSort = order == Order.NameAsc ? Order.NameDesc : Order.NameAsc;
ViewBag.AgeSort = order == Order.AgeAsc ? Order.AgeDesc : Order.AgeAsc;
switch (order)
{
case Order.AgeDesc:
users = users.OrderByDescending(u => u.Age);
break;
case Order.AgeAsc:
users = users.OrderBy(u => u.Age);
break;
case Order.NameDesc:
users = users.OrderByDescending(u => u.Name);
break;
default:
users = users.OrderBy(u => u.Name);
break;
}
UsersViewModel model = new UsersViewModel
{
Filter = filteringCriterionByName,
Users = users.ToArray(),
PageViewModel = new PageViewModel(page, count, pageSize )
};
var model = await _userService.GetAll(order, filterByName, pageSize, page);
return View(model);
}
......
using System.Linq;
using PhoneStore.Models;
using PhoneStore.ViewModels;
namespace PhoneStore.Helpers
{
public static class UserHelper
{
public static UsersViewModel MapToUsersViewModel(
this IQueryable<User> self,
string filter,
int page,
int count,
int pageSize)
{
return new UsersViewModel
{
Users = self.ToArray(),
Filter = filter,
PageViewModel = new PageViewModel(page, count, pageSize)
};
}
}
}
\ No newline at end of file
using System.Linq;
using System.Threading.Tasks;
using PhoneStore.Models;
namespace PhoneStore.Services.Abstractions
{
public interface IPaginationService
{
Task<(IQueryable<User>, int)> GetABatchOfData(IQueryable<User> users, int page, int pageSize);
}
}
\ No newline at end of file
using System.Threading.Tasks;
using PhoneStore.Enums;
using PhoneStore.ViewModels;
namespace PhoneStore.Services.Abstractions
{
public interface IUserService
{
Task<UsersViewModel> GetAll(Order order, string filterByName, int pageSize, int page);
}
}
\ No newline at end of file
using System.Linq;
using PhoneStore.Models;
namespace PhoneStore.Services.Abstractions
{
public interface IUsersFilter
{
IQueryable<User> FilterByName(IQueryable<User> users, string filterByName);
}
}
\ No newline at end of file
using System.Linq;
using PhoneStore.Models;
using Order = PhoneStore.Enums.Order;
namespace PhoneStore.Services.Abstractions
{
public interface IUsersSortService
{
IQueryable<User> Sort(IQueryable<User> users, Order order);
}
}
\ No newline at end of file
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using PhoneStore.Models;
using PhoneStore.Services.Abstractions;
namespace PhoneStore.Services
{
public class PaginationService : IPaginationService
{
public async Task<(IQueryable<User>, int)> GetABatchOfData(IQueryable<User> users, int page, int pageSize)
{
int count = await users.CountAsync();
return (users.Skip((page - 1) * pageSize).Take(pageSize), count);
}
}
}
\ No newline at end of file
using System.Linq;
using System.Threading.Tasks;
using PhoneStore.Helpers;
using PhoneStore.Models;
using PhoneStore.Services.Abstractions;
using PhoneStore.ViewModels;
using Order = PhoneStore.Enums.Order;
namespace PhoneStore.Services
{
public class UserService : IUserService
{
private readonly MobileContext _db;
private readonly IUsersSortService _sortService;
private readonly IUsersFilter _usersFilter;
private readonly IPaginationService _paginationService;
public UserService(
MobileContext db,
IUsersSortService sortService,
IUsersFilter usersFilter,
IPaginationService paginationService)
{
_db = db;
_sortService = sortService;
_usersFilter = usersFilter;
_paginationService = paginationService;
}
public async Task<UsersViewModel> GetAll(Order order, string filterByName, int pageSize, int page)
{
var users = _db.Users.AsQueryable();
var filteredUsers = _usersFilter.FilterByName(users, filterByName);
var sortedUsers = _sortService.Sort(filteredUsers, order);
var paginationData = await _paginationService.GetABatchOfData(sortedUsers, page, pageSize);
return paginationData.Item1.MapToUsersViewModel(filterByName, page, paginationData.Item2, pageSize);
}
}
}
\ No newline at end of file
using System.Linq;
using PhoneStore.Models;
using PhoneStore.Services.Abstractions;
namespace PhoneStore.Services
{
public class UsersFilter : IUsersFilter
{
public IQueryable<User> FilterByName(IQueryable<User> users, string filterByName)
{
return string.IsNullOrEmpty(filterByName)
? users
: users.Where(u => u.Name.Contains(filterByName));
}
}
}
\ No newline at end of file
using System.Linq;
using System.Threading.Tasks;
using PhoneStore.Models;
using PhoneStore.Services.Abstractions;
using Order = PhoneStore.Enums.Order;
namespace PhoneStore.Services
{
public class UsersSortService : IUsersSortService
{
public IQueryable<User> Sort(IQueryable<User> users, Order order)
{
switch (order)
{
case Order.AgeDesc:
return users.OrderByDescending(u => u.Age);
case Order.AgeAsc:
return users.OrderBy(u => u.Age);
case Order.NameDesc:
return users.OrderByDescending(u => u.Name);
default: return users.OrderBy(u => u.Name);
}
}
}
}
\ No newline at end of file
......@@ -32,6 +32,10 @@ namespace PhoneStore
services.AddTransient<IDefaultPhoneImagePathProvider>(_ =>
new DefaultPhoneImagePathProvider(Configuration["PathToDefaultAvatar:Path"]));
services.AddTransient<IPhoneService, PhoneService>();
services.AddTransient<IUserService, UserService>();
services.AddTransient<IUsersSortService, UsersSortService>();
services.AddTransient<IUsersFilter, UsersFilter>();
services.AddTransient<IPaginationService, PaginationService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......
......@@ -13,10 +13,10 @@
<div class="form_row">
<label for="name">
Имя:
<input
id="name"
type="text"
name="filteringCriterionByName"
<input
id="name"
type="text"
name="filterByName"
value="@Model.Filter">
</label>
<input type="text" hidden name="page" value="@Model.PageViewModel.Page">
......@@ -33,7 +33,7 @@
asp-action="Index"
asp-controller="Users"
asp-route-order="@ViewBag.NameSort"
asp-route-filteringCriterionByName="@Model.Filter">
asp-route-filterByName="@Model.Filter">
Имя
</a>
</th>
......@@ -42,7 +42,7 @@
asp-action="Index"
asp-controller="Users"
asp-route-order="@ViewBag.AgeSort"
asp-route-filteringCriterionByName="@Model.Filter">
asp-route-filterByName="@Model.Filter">
Возраст
</a>
</th>
......@@ -55,18 +55,23 @@
</tr>
}
</table>
@if (Model.PageViewModel.HasPrevious)
{
<a asp-action="Index" asp-controller="Users"
asp-route-page="@(Model.PageViewModel.Page - 1)"
asp-route-filteringCriterionByName="@Model.Filter"
class="btn btn-outline-warning">Назад</a>
<a
asp-action="Index"
asp-controller="Users"
asp-route-page="@(Model.PageViewModel.Page - 1)" class="btn btn-outline-warning"
asp-route-filterByName="@Model.Filter">
Назад
</a>
}
@if (Model.PageViewModel.HasNext)
{
<a asp-action="Index" asp-controller="Users"
asp-route-page="@(Model.PageViewModel.Page + 1)"
asp-route-filteringCriterionByName="@Model.Filter"
class="btn btn-outline-warning">Вперед</a>
<a
asp-action="Index"
asp-controller="Users"
asp-route-page="@(Model.PageViewModel.Page + 1)" class="btn btn-outline-warning"
asp-route-filterByName="@Model.Filter">
Вперед
</a>
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment