A bit of an improvement in paging

- generic collection and display but only used for search results at the moment and does nothing for other queries. in other words, build your own IPageOfItems

--HG--
branch : dev
This commit is contained in:
Nathan Heskew
2010-06-07 15:52:26 -07:00
parent 8adc118803
commit a273c13205
9 changed files with 88 additions and 46 deletions

View File

@@ -15,29 +15,17 @@ namespace Orchard.Search.Controllers {
_contentManager = contentManager;
}
public ActionResult Index(string q, int page = 0, int pageSize = 0) {
var take = pageSize > 0 ? pageSize : 10;
var skip = (page > 0 ? page - 1 : 0) * take;
public ActionResult Index(string q, int page = 1, int pageSize = 10) {
var searchViewModel = new SearchViewModel {
Query = q,
Page = page > 0 ? page : 1,
PageSize = take
DefaultPageSize = 10, // <- yeah, I know :|
PageOfResults = _searchService.Query(q, page, pageSize, searchHit => new SearchResultViewModel {
Content = _contentManager.BuildDisplayModel(_contentManager.Get(searchHit.Id), "SummaryForSearch"),
SearchHit = searchHit
})
};
var results = _searchService.Query(q, skip, take);
if (results == null)
return View(searchViewModel);
searchViewModel.Count = results.TotalCount;
searchViewModel.TotalPageCount = (int)Math.Ceiling((decimal)searchViewModel.Count/searchViewModel.PageSize);
//todo: deal with page requests beyond result count
searchViewModel.ResultsPage = results.Page
.Select(result => new SearchResultViewModel {
Content = _contentManager.BuildDisplayModel(_contentManager.Get(result.Id), "SummaryForSearch"),
SearchHit = result
})
.ToList();
return View(searchViewModel);
}

View File

@@ -1,10 +1,11 @@
using System;
using Orchard.Search.Models;
using Orchard.Collections;
using Orchard.Indexing;
namespace Orchard.Search.Services {
public interface ISearchService : IDependency {
bool HasIndexToManage { get; }
ISearchResult Query(string query, int skip, int? take);
IPageOfItems<T> Query<T>(string query, int skip, int? take, Func<ISearchHit, T> shapeResult);
void RebuildIndex();
void UpdateIndex();
DateTime GetIndexUpdatedUtc();

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Collections;
using Orchard.Indexing;
using Orchard.Localization;
using Orchard.Search.Models;
@@ -27,23 +29,27 @@ namespace Orchard.Search.Services
get { return _indexManager.HasIndexProvider(); }
}
ISearchResult ISearchService.Query(string query, int skip, int? take) {
IPageOfItems<T> ISearchService.Query<T>(string query, int page, int? pageSize, Func<ISearchHit, T> shapeResult) {
if (string.IsNullOrWhiteSpace(query) || !_indexManager.HasIndexProvider())
return null;
var searchBuilder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(SearchIndexName)
var searchBuilder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(SearchIndexName)
.WithField("title", query)
.WithField("body", query);
var totalCount = searchBuilder.Count();
if (take != null)
if (pageSize != null)
searchBuilder = searchBuilder
.Slice(skip, (int)take);
.Slice((page > 0 ? page - 1 : 0) * (int)pageSize, (int)pageSize);
return new SearchResult {
Page = searchBuilder.Search(),
TotalCount = totalCount
var pageOfItems = new PageOfItems<T>(searchBuilder.Search().Select(shapeResult)) {
PageNumber = page,
PageSize = pageSize != null ? (int) pageSize : totalCount,
TotalItemCount = totalCount
};
return pageOfItems;
}
void ISearchService.RebuildIndex() {

View File

@@ -1,13 +1,10 @@
using System.Collections.Generic;
using Orchard.Collections;
using Orchard.Mvc.ViewModels;
namespace Orchard.Search.ViewModels {
public class SearchViewModel : BaseViewModel {
public IEnumerable<SearchResultViewModel> ResultsPage { get; set; }
public int Count { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int TotalPageCount { get; set; }
public string Query { get; set; }
public int DefaultPageSize { get; set; }
public IPageOfItems<SearchResultViewModel> PageOfResults { get; set; }
}
}

View File

@@ -4,14 +4,14 @@ Html.RegisterStyle("search.css"); %>
<h1><%=Html.TitleForPage(T("Search").Text)%></h1><%
Html.Zone("search");
if (!string.IsNullOrWhiteSpace(Model.Query)) {
if (Model.Count == 0) { %>
if (Model.PageOfResults.Count() == 0) { %>
<p class="search-summary"><%=T("<em>zero</em> results") %></p><%
}
else { %>
<p class="search-summary"><%=T("<em>{0} - {1}</em> of <em>{2}</em> results", (Model.Page - 1) * Model.PageSize + 1, Model.Page * Model.PageSize > Model.Count ? Model.Count : Model.Page * Model.PageSize, Model.Count)%></p><%
<p class="search-summary"><%=T("<em>{0} - {1}</em> of <em>{2}</em> results", Model.PageOfResults.StartPosition, Model.PageOfResults.EndPosition, Model.PageOfResults.TotalItemCount)%></p><%
}
}
if (Model.ResultsPage != null && Model.ResultsPage.Count() > 0) { %>
<%=Html.UnorderedList(Model.ResultsPage, (r, i) => Html.DisplayForItem(r.Content).ToHtmlString(), "search-results contentItems") %>
<%=Html.Pager(Model.TotalPageCount, Model.Page, new {q = Model.Query}) %><%
if (Model.PageOfResults != null && Model.PageOfResults.Count() > 0) { %>
<%=Html.UnorderedList(Model.PageOfResults, (r, i) => Html.DisplayForItem(r.Content).ToHtmlString() , "search-results contentItems") %>
<%=Html.Pager(Model.PageOfResults, Model.PageOfResults.PageNumber, Model.DefaultPageSize, new {q = Model.Query}) %><%
} %>

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Orchard.Collections {
public interface IPageOfItems<out T> : IEnumerable<T> {
int PageNumber { get; set; }
int PageSize { get; set; }
int TotalItemCount { get; set; }
int TotalPageCount { get; }
int StartPosition { get; }
int EndPosition { get; }
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
namespace Orchard.Collections {
public class PageOfItems<T> : List<T>, IPageOfItems<T> {
public PageOfItems(IEnumerable<T> items) {
AddRange(items);
}
#region IPageOfItems<T> Members
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalItemCount { get; set; }
public int TotalPageCount {
get { return (int) Math.Ceiling((double) TotalItemCount/PageSize); }
}
public int StartPosition {
get { return (PageNumber - 1)*PageSize + 1; }
}
public int EndPosition {
get { return PageNumber * PageSize > TotalItemCount ? TotalItemCount : PageNumber * PageSize; }
}
#endregion
}
}

View File

@@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using Orchard.Collections;
using Orchard.Mvc.ViewModels;
using Orchard.Services;
using Orchard.Settings;
@@ -40,21 +40,25 @@ namespace Orchard.Mvc.Html {
return MvcHtmlString.Create(builder.ToString(TagRenderMode.Normal));
}
#region Pager
public static string Pager(this HtmlHelper html, int pageCount, int currentPage, object values = null, string previousText = "<", string nextText = ">", bool alwaysShowPreviousAndNext = false) {
if (pageCount < 2)
public static string Pager<T>(this HtmlHelper html, IPageOfItems<T> pageOfItems, int currentPage, int defaultPageSize, object values = null, string previousText = "<", string nextText = ">", bool alwaysShowPreviousAndNext = false) {
if (pageOfItems.TotalPageCount < 2)
return "";
var sb = new StringBuilder(75);
var rvd = new RouteValueDictionary {{"q", ""},{"page", 0}};
var viewContext = html.ViewContext;
var rvd = new RouteValueDictionary();
var urlHelper = new UrlHelper(viewContext.RequestContext);
if (pageOfItems.PageSize != defaultPageSize)
rvd.Add("pagesize", pageOfItems.PageSize);
foreach (var item in viewContext.RouteData.Values) {
rvd.Add(item.Key, item.Value);
}
var urlHelper = new UrlHelper(viewContext.RequestContext);
if (values != null) {
var rvd2 = new RouteValueDictionary(values);
@@ -77,18 +81,22 @@ namespace Orchard.Mvc.Html {
}
//todo: when there are many pages (> 15?) maybe do something like 1 2 3...6 7 8...13 14 15
for (var p = 1; p <= pageCount; p++) {
for (var p = 1; p <= pageOfItems.TotalPageCount; p++) {
if (p == currentPage) {
sb.AppendFormat(" <span>{0}</span>", p);
}
else {
rvd["page"] = p;
if (p == 1)
rvd.Remove("page");
else
rvd["page"] = p;
sb.AppendFormat(" <a href=\"{1}\">{0}</a>", p,
urlHelper.RouteUrl(rvd));
}
}
if (currentPage < pageCount || alwaysShowPreviousAndNext) {
if (currentPage < pageOfItems.TotalPageCount || alwaysShowPreviousAndNext) {
rvd["page"] = currentPage + 1;
sb.AppendFormat("<a href=\"{1}\" class=\"next\">{0}</a>", nextText,
urlHelper.RouteUrl(rvd));

View File

@@ -130,6 +130,8 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Collections\IPageOfItems.cs" />
<Compile Include="Collections\PageOfItems.cs" />
<Compile Include="ContentManagement\Aspects\ICommonAspect.cs">
<SubType>Code</SubType>
</Compile>