mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Making existing paginiation implementations a bit more consistent.
For Blog (posts) and Search. --HG-- branch : dev
This commit is contained in:
@@ -370,6 +370,7 @@
|
|||||||
<Content Include="Routable\Views\Routable.HomePage.cshtml" />
|
<Content Include="Routable\Views\Routable.HomePage.cshtml" />
|
||||||
<Content Include="Localization\Views\Parts\Localization.ContentTranslations.SummaryAdmin.cshtml" />
|
<Content Include="Localization\Views\Parts\Localization.ContentTranslations.SummaryAdmin.cshtml" />
|
||||||
<Content Include="Contents\Views\Items\Content.Summary.cshtml" />
|
<Content Include="Contents\Views\Items\Content.Summary.cshtml" />
|
||||||
|
<Content Include="Shapes\Views\Pager.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
||||||
|
|||||||
39
src/Orchard.Web/Core/Shapes/Views/Pager.cshtml
Normal file
39
src/Orchard.Web/Core/Shapes/Views/Pager.cshtml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
@{
|
||||||
|
var nextText = HasText(Model.NextText) ? Model.NextText : T("Older").Text;
|
||||||
|
var previousText = HasText(Model.PreviousText) ? Model.PreviousText : T("Newer").Text;
|
||||||
|
|
||||||
|
var routeData = new RouteValueDictionary(ViewContext.RouteData.Values);
|
||||||
|
var queryString = ViewContext.HttpContext.Request.QueryString;
|
||||||
|
if (queryString != null) {
|
||||||
|
foreach (string key in queryString.Keys) {
|
||||||
|
if (!routeData.ContainsKey(key)) {
|
||||||
|
var value = queryString[key];
|
||||||
|
routeData[key] = queryString[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (routeData.ContainsKey("id") && !HasText(routeData["id"])) {
|
||||||
|
routeData.Remove("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
Model.Classes.Add("pager");
|
||||||
|
Model.Classes.Add("group");
|
||||||
|
var tag = Tag(Model, "ul");
|
||||||
|
}
|
||||||
|
@if (Model.HasNextPage || Model.Page > 1) {
|
||||||
|
@tag.StartElement
|
||||||
|
if(Model.HasNextPage) {
|
||||||
|
routeData["page"] = Model.Page + 1;
|
||||||
|
<li class="older">
|
||||||
|
@Html.ActionLink((string)nextText, (string)routeData["action"], (string)routeData["controller"], routeData, null)
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
if(Model.Page > 1) {
|
||||||
|
routeData["page"] = Model.Page - 1;
|
||||||
|
<li class="newer">
|
||||||
|
@Html.ActionLink((string)previousText, (string)routeData["action"], (string)routeData["controller"], routeData, null)
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
@tag.EndElement
|
||||||
|
}
|
||||||
@@ -140,6 +140,12 @@ namespace Orchard.Blogs.Controllers {
|
|||||||
|
|
||||||
if (blogPart == null)
|
if (blogPart == null)
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
|
//() => {
|
||||||
|
// var list = shapeHelper.List();
|
||||||
|
// list.AddRange(_blogPostService.Get(part, VersionOptions.Latest)
|
||||||
|
// .Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin")));
|
||||||
|
// return shapeHelper.Parts_Blogs_BlogPost_List_Admin(ContentPart: part, ContentItems: list);
|
||||||
|
//})
|
||||||
|
|
||||||
var model = Services.ContentManager.BuildDisplay(blogPart, "DetailAdmin");
|
var model = Services.ContentManager.BuildDisplay(blogPart, "DetailAdmin");
|
||||||
return View(model);
|
return View(model);
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ using System.Web;
|
|||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Orchard.Blogs.Extensions;
|
||||||
using Orchard.Blogs.Models;
|
using Orchard.Blogs.Models;
|
||||||
using Orchard.Blogs.Routing;
|
using Orchard.Blogs.Routing;
|
||||||
using Orchard.Blogs.Services;
|
using Orchard.Blogs.Services;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.Core.Feeds;
|
||||||
using Orchard.DisplayManagement;
|
using Orchard.DisplayManagement;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Themes;
|
using Orchard.Themes;
|
||||||
|
using Orchard.UI.Navigation;
|
||||||
|
|
||||||
namespace Orchard.Blogs.Controllers {
|
namespace Orchard.Blogs.Controllers {
|
||||||
[Themed]
|
[Themed]
|
||||||
@@ -18,6 +20,7 @@ namespace Orchard.Blogs.Controllers {
|
|||||||
private readonly IBlogService _blogService;
|
private readonly IBlogService _blogService;
|
||||||
private readonly IBlogPostService _blogPostService;
|
private readonly IBlogPostService _blogPostService;
|
||||||
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
||||||
|
private readonly IFeedManager _feedManager;
|
||||||
private readonly RouteCollection _routeCollection;
|
private readonly RouteCollection _routeCollection;
|
||||||
|
|
||||||
public BlogController(
|
public BlogController(
|
||||||
@@ -25,12 +28,14 @@ namespace Orchard.Blogs.Controllers {
|
|||||||
IBlogService blogService,
|
IBlogService blogService,
|
||||||
IBlogPostService blogPostService,
|
IBlogPostService blogPostService,
|
||||||
IBlogSlugConstraint blogSlugConstraint,
|
IBlogSlugConstraint blogSlugConstraint,
|
||||||
|
IFeedManager feedManager,
|
||||||
RouteCollection routeCollection,
|
RouteCollection routeCollection,
|
||||||
IShapeFactory shapeFactory) {
|
IShapeFactory shapeFactory) {
|
||||||
_services = services;
|
_services = services;
|
||||||
_blogService = blogService;
|
_blogService = blogService;
|
||||||
_blogPostService = blogPostService;
|
_blogPostService = blogPostService;
|
||||||
_blogSlugConstraint = blogSlugConstraint;
|
_blogSlugConstraint = blogSlugConstraint;
|
||||||
|
_feedManager = feedManager;
|
||||||
_routeCollection = routeCollection;
|
_routeCollection = routeCollection;
|
||||||
Logger = NullLogger.Instance;
|
Logger = NullLogger.Instance;
|
||||||
Shape = shapeFactory;
|
Shape = shapeFactory;
|
||||||
@@ -51,10 +56,7 @@ namespace Orchard.Blogs.Controllers {
|
|||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: (erikpo) Should move the slug parameter and get call and null check up into a model binder
|
public ActionResult Item(string blogSlug, Pager pager) {
|
||||||
public ActionResult Item(string blogSlug, int page) {
|
|
||||||
const int pageSize = 10;
|
|
||||||
|
|
||||||
var correctedSlug = _blogSlugConstraint.FindSlug(blogSlug);
|
var correctedSlug = _blogSlugConstraint.FindSlug(blogSlug);
|
||||||
if (correctedSlug == null)
|
if (correctedSlug == null)
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
@@ -63,21 +65,18 @@ namespace Orchard.Blogs.Controllers {
|
|||||||
if (blogPart == null)
|
if (blogPart == null)
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
|
|
||||||
var blogPosts = _blogPostService.Get(blogPart, (page - 1) * pageSize, pageSize)
|
_feedManager.Register(blogPart);
|
||||||
|
var blogPosts = _blogPostService.Get(blogPart, pager.GetStartIndex(), pager.PageSize)
|
||||||
.Select(b => _services.ContentManager.BuildDisplay(b, "Summary"));
|
.Select(b => _services.ContentManager.BuildDisplay(b, "Summary"));
|
||||||
|
|
||||||
blogPart.As<BlogPagerPart>().Page = page;
|
|
||||||
blogPart.As<BlogPagerPart>().PageSize = pageSize;
|
|
||||||
blogPart.As<BlogPagerPart>().BlogSlug = correctedSlug;
|
|
||||||
blogPart.As<BlogPagerPart>().ThereIsANextPage = _blogPostService.Get(blogPart, (page) * pageSize, pageSize).Any();
|
|
||||||
|
|
||||||
var blog = _services.ContentManager.BuildDisplay(blogPart);
|
var blog = _services.ContentManager.BuildDisplay(blogPart);
|
||||||
|
|
||||||
var list = Shape.List();
|
var list = Shape.List();
|
||||||
list.AddRange(blogPosts);
|
list.AddRange(blogPosts);
|
||||||
|
|
||||||
blog.Content.Add(Shape.Parts_Blogs_BlogPost_List(ContentItems: list), "5");
|
blog.Content.Add(Shape.Parts_Blogs_BlogPost_List(ContentItems: list), "5");
|
||||||
|
|
||||||
|
var hasNextPage = _blogPostService.Get(blogPart, pager.GetStartIndex(pager.Page + 1), 1).Any();
|
||||||
|
blog.Content.Add(Shape.Pager(pager).HasNextPage(hasNextPage), "Content:after");
|
||||||
|
|
||||||
return View(blog);
|
return View(blog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
using Orchard.Blogs.Models;
|
|
||||||
using Orchard.ContentManagement.Drivers;
|
|
||||||
|
|
||||||
namespace Orchard.Blogs.Drivers {
|
|
||||||
public class BlogPagerPartDriver : ContentPartDriver<BlogPagerPart> {
|
|
||||||
protected override DriverResult Display(BlogPagerPart part, string displayType, dynamic shapeHelper) {
|
|
||||||
return ContentShape("Parts_Blogs_Blog_Pager",
|
|
||||||
() => shapeHelper.Parts_Blogs_Blog_Pager(ContentPart: part, Page: part.Page, PageSize: part.PageSize, BlogSlug: part.BlogSlug, ThereIsANextPage: part.ThereIsANextPage));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -41,24 +41,25 @@ namespace Orchard.Blogs.Drivers {
|
|||||||
ContentShape("Parts_Blogs_Blog_Description",
|
ContentShape("Parts_Blogs_Blog_Description",
|
||||||
() => shapeHelper.Parts_Blogs_Blog_Description(ContentPart: part, Description: part.Description)),
|
() => shapeHelper.Parts_Blogs_Blog_Description(ContentPart: part, Description: part.Description)),
|
||||||
ContentShape("Parts_Blogs_Blog_BlogPostCount",
|
ContentShape("Parts_Blogs_Blog_BlogPostCount",
|
||||||
() => shapeHelper.Parts_Blogs_Blog_BlogPostCount(ContentPart: part, PostCount: part.PostCount)),
|
() => shapeHelper.Parts_Blogs_Blog_BlogPostCount(ContentPart: part, PostCount: part.PostCount))
|
||||||
|
//,
|
||||||
// todo: (heskew) implement a paging solution that doesn't require blog posts to be tied to the blog within the controller
|
// todo: (heskew) implement a paging solution that doesn't require blog posts to be tied to the blog within the controller
|
||||||
ContentShape("Parts_Blogs_BlogPost_List",
|
//ContentShape("Parts_Blogs_BlogPost_List",
|
||||||
() => {
|
// () => {
|
||||||
_feedManager.Register(part);
|
// _feedManager.Register(part);
|
||||||
return null;
|
|
||||||
// var list = shapeHelper.List();
|
// var list = shapeHelper.List();
|
||||||
// list.AddRange(_blogPostService.Get(part)
|
// list.AddRange(_blogPostService.Get(part)
|
||||||
// .Select(bp => _contentManager.BuildDisplay(bp, "Summary")));
|
// .Select(bp => _contentManager.BuildDisplay(bp, "Summary")));
|
||||||
// return shapeHelper.Parts_Blogs_BlogPost_List(ContentPart: part, ContentItems: list);
|
// return shapeHelper.Parts_Blogs_BlogPost_List(ContentPart: part, ContentItems: list);
|
||||||
}),
|
// }),
|
||||||
ContentShape("Parts_Blogs_BlogPost_List_Admin",
|
//ContentShape("Parts_Blogs_BlogPost_List_Admin",
|
||||||
() => {
|
// () =>
|
||||||
var list = shapeHelper.List();
|
// {
|
||||||
list.AddRange(_blogPostService.Get(part, VersionOptions.Latest)
|
// var list = shapeHelper.List();
|
||||||
.Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin")));
|
// list.AddRange(_blogPostService.Get(part, VersionOptions.Latest)
|
||||||
return shapeHelper.Parts_Blogs_BlogPost_List_Admin(ContentPart: part, ContentItems: list);
|
// .Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin")));
|
||||||
})
|
// return shapeHelper.Parts_Blogs_BlogPost_List_Admin(ContentPart: part, ContentItems: list);
|
||||||
|
// })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Data;
|
using Orchard.ContentManagement.MetaData;
|
||||||
using Orchard.ContentManagement.MetaData;
|
|
||||||
using Orchard.Data.Migration;
|
using Orchard.Data.Migration;
|
||||||
|
|
||||||
namespace Orchard.Blogs {
|
namespace Orchard.Blogs {
|
||||||
@@ -40,7 +39,6 @@ namespace Orchard.Blogs {
|
|||||||
.WithPart("BlogPart")
|
.WithPart("BlogPart")
|
||||||
.WithPart("CommonPart")
|
.WithPart("CommonPart")
|
||||||
.WithPart("RoutePart")
|
.WithPart("RoutePart")
|
||||||
.WithPart("BlogPagerPart")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentDefinitionManager.AlterTypeDefinition("BlogPost",
|
ContentDefinitionManager.AlterTypeDefinition("BlogPost",
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
using Orchard.ContentManagement;
|
|
||||||
|
|
||||||
namespace Orchard.Blogs.Models {
|
|
||||||
public class BlogPagerPart : ContentPart {
|
|
||||||
public int Page { get; set; }
|
|
||||||
public int PageSize { get; set; }
|
|
||||||
public string BlogSlug { get; set; }
|
|
||||||
public bool ThereIsANextPage { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -68,14 +68,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AdminMenu.cs" />
|
<Compile Include="AdminMenu.cs" />
|
||||||
<Compile Include="Drivers\BlogArchivesPartDriver.cs" />
|
<Compile Include="Drivers\BlogArchivesPartDriver.cs" />
|
||||||
<Compile Include="Drivers\BlogPagerPartDriver.cs" />
|
|
||||||
<Compile Include="Drivers\RemoteBlogPublishingDriver.cs" />
|
<Compile Include="Drivers\RemoteBlogPublishingDriver.cs" />
|
||||||
<Compile Include="Drivers\RecentBlogPostsPartDriver.cs" />
|
<Compile Include="Drivers\RecentBlogPostsPartDriver.cs" />
|
||||||
<Compile Include="Handlers\BlogArchivesPartHandler.cs" />
|
<Compile Include="Handlers\BlogArchivesPartHandler.cs" />
|
||||||
<Compile Include="Handlers\RecentBlogPostsPartHandler.cs" />
|
<Compile Include="Handlers\RecentBlogPostsPartHandler.cs" />
|
||||||
<Compile Include="Models\BlogArchivesPart.cs" />
|
<Compile Include="Models\BlogArchivesPart.cs" />
|
||||||
<Compile Include="Models\BlogArchivesPartRecord.cs" />
|
<Compile Include="Models\BlogArchivesPartRecord.cs" />
|
||||||
<Compile Include="Models\BlogPagerPart.cs" />
|
|
||||||
<Compile Include="Models\RecentBlogPostsPart.cs" />
|
<Compile Include="Models\RecentBlogPostsPart.cs" />
|
||||||
<Compile Include="Models\RecentBlogPostsPartRecord.cs" />
|
<Compile Include="Models\RecentBlogPostsPartRecord.cs" />
|
||||||
<Compile Include="ResourceManifest.cs" />
|
<Compile Include="ResourceManifest.cs" />
|
||||||
@@ -120,7 +118,6 @@
|
|||||||
<Content Include="Scripts\archives.js" />
|
<Content Include="Scripts\archives.js" />
|
||||||
<Content Include="Styles\admin.css" />
|
<Content Include="Styles\admin.css" />
|
||||||
<Content Include="Styles\archives.css" />
|
<Content Include="Styles\archives.css" />
|
||||||
<Content Include="Styles\pagination.css" />
|
|
||||||
<Content Include="Views\BlogAdmin\Create.cshtml" />
|
<Content Include="Views\BlogAdmin\Create.cshtml" />
|
||||||
<Content Include="Views\BlogAdmin\Edit.cshtml" />
|
<Content Include="Views\BlogAdmin\Edit.cshtml" />
|
||||||
<Content Include="Views\BlogAdmin\Item.cshtml" />
|
<Content Include="Views\BlogAdmin\Item.cshtml" />
|
||||||
@@ -164,7 +161,6 @@
|
|||||||
<Content Include="Views\Items\Content-Blog.Edit.cshtml" />
|
<Content Include="Views\Items\Content-Blog.Edit.cshtml" />
|
||||||
<Content Include="Views\Items\Content-BlogPost.Editor.cshtml" />
|
<Content Include="Views\Items\Content-BlogPost.Editor.cshtml" />
|
||||||
<Content Include="Views\Parts\Blogs.BlogPost.List.cshtml" />
|
<Content Include="Views\Parts\Blogs.BlogPost.List.cshtml" />
|
||||||
<Content Include="Views\Parts\Blogs.Blog.Pager.cshtml" />
|
|
||||||
<Content Include="Views\Parts\Blogs.RecentBlogPosts.cshtml" />
|
<Content Include="Views\Parts\Blogs.RecentBlogPosts.cshtml" />
|
||||||
<Content Include="Views\Parts\Blogs.Blog.BlogPostCount.cshtml" />
|
<Content Include="Views\Parts\Blogs.Blog.BlogPostCount.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
Parts_Blogs_Blog_Manage
|
Parts_Blogs_Blog_Manage
|
||||||
Parts_Blogs_Blog_Description
|
Parts_Blogs_Blog_Description
|
||||||
Parts_Blogs_Blog_BlogPostCount
|
Parts_Blogs_Blog_BlogPostCount
|
||||||
Parts_Blogs_Blog_Pager
|
|
||||||
Parts_Blogs_BlogPost_List -> when in the blog detail display the blog post list is currently hard-coded to Content:5 to enable the current state of blog paging
|
Parts_Blogs_BlogPost_List -> when in the blog detail display the blog post list is currently hard-coded to Content:5 to enable the current state of blog paging
|
||||||
Parts_Blogs_BlogPost_List_Admin
|
Parts_Blogs_BlogPost_List_Admin
|
||||||
-->
|
-->
|
||||||
@@ -23,7 +22,6 @@
|
|||||||
...placing it in in the Content zone as it's currently implemented to light up the RSS feed for the blog... -->
|
...placing it in in the Content zone as it's currently implemented to light up the RSS feed for the blog... -->
|
||||||
<!-- Parts_Blogs_RemotePublishing is made available with the "Remote Blog Publishing" feature -->
|
<!-- Parts_Blogs_RemotePublishing is made available with the "Remote Blog Publishing" feature -->
|
||||||
<Place Parts_Blogs_BlogPost_List="Content"
|
<Place Parts_Blogs_BlogPost_List="Content"
|
||||||
Parts_Blogs_Blog_Pager="Content:after"
|
|
||||||
Parts_Blogs_Blog_Description="Content:before"
|
Parts_Blogs_Blog_Description="Content:before"
|
||||||
Parts_Blogs_RemotePublishing="Content"/>
|
Parts_Blogs_RemotePublishing="Content"/>
|
||||||
</Match>
|
</Match>
|
||||||
|
|||||||
@@ -261,32 +261,13 @@ namespace Orchard.Blogs {
|
|||||||
Priority = 11,
|
Priority = 11,
|
||||||
Route = new Route(
|
Route = new Route(
|
||||||
"{blogSlug}",
|
"{blogSlug}",
|
||||||
new RouteValueDictionary {
|
|
||||||
{"area", "Orchard.Blogs"},
|
|
||||||
{"controller", "Blog"},
|
|
||||||
{"action", "Item"},
|
|
||||||
{"page", 1}
|
|
||||||
},
|
|
||||||
new RouteValueDictionary {
|
|
||||||
{"blogSlug", _blogSlugConstraint}
|
|
||||||
},
|
|
||||||
new RouteValueDictionary {
|
|
||||||
{"area", "Orchard.Blogs"}
|
|
||||||
},
|
|
||||||
new MvcRouteHandler())
|
|
||||||
},
|
|
||||||
new RouteDescriptor {
|
|
||||||
Priority = 11,
|
|
||||||
Route = new Route(
|
|
||||||
"{blogSlug}/Page/{*page}",
|
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Orchard.Blogs"},
|
{"area", "Orchard.Blogs"},
|
||||||
{"controller", "Blog"},
|
{"controller", "Blog"},
|
||||||
{"action", "Item"}
|
{"action", "Item"}
|
||||||
},
|
},
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"blogSlug", _blogSlugConstraint},
|
{"blogSlug", _blogSlugConstraint}
|
||||||
{"page", @"^\d+$"}
|
|
||||||
},
|
},
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Orchard.Blogs"}
|
{"area", "Orchard.Blogs"}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
ul.pagination
|
|
||||||
{
|
|
||||||
list-style-type:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.pagination li a
|
|
||||||
{
|
|
||||||
font-size:13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.pagination li.newer
|
|
||||||
{
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.pagination li.older
|
|
||||||
{
|
|
||||||
float:right;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
@using Orchard.Blogs.Extensions;
|
|
||||||
@{
|
|
||||||
Style.Include("pagination.css");
|
|
||||||
}
|
|
||||||
@if (Model.ThereIsANextPage || Model.Page > 1) {
|
|
||||||
<ul class="blog-pagination group">
|
|
||||||
@if(Model.ThereIsANextPage) {
|
|
||||||
<li class="older">
|
|
||||||
@Html.ActionLink(T("Older Posts").Text, "Item", new { Area = "Orchard.Blogs", blogSlug = Model.BlogSlug, page = Model.Page + 1 })
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
@if(Model.Page > 1) {
|
|
||||||
<li class="newer">
|
|
||||||
@Html.ActionLink(T("Newer Posts").Text, "Item", new { Area = "Orchard.Blogs", blogSlug = Model.BlogSlug, page = Model.Page - 1 })
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
}
|
|
||||||
@@ -8,5 +8,5 @@ Features:
|
|||||||
Orchard.ContentQueries:
|
Orchard.ContentQueries:
|
||||||
Name: Queried Content Lists
|
Name: Queried Content Lists
|
||||||
Description: Use simple queries to create orderd lists of content items with optional paging support.
|
Description: Use simple queries to create orderd lists of content items with optional paging support.
|
||||||
Dependencies: Contents
|
Dependencies: Contents, Common
|
||||||
Category: Content
|
Category: Content
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
using System.Web.Mvc;
|
using System.Linq;
|
||||||
using System.Web.Query.Dynamic;
|
using System.Web.Mvc;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.DisplayManagement;
|
||||||
using Orchard.Indexing;
|
using Orchard.Indexing;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Search.Services;
|
using Orchard.Search.Services;
|
||||||
using Orchard.Search.ViewModels;
|
using Orchard.Search.ViewModels;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
using Orchard.Search.Models;
|
using Orchard.Search.Models;
|
||||||
|
using Orchard.UI.Navigation;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Orchard.Collections;
|
using Orchard.Collections;
|
||||||
@@ -22,21 +24,23 @@ namespace Orchard.Search.Controllers {
|
|||||||
public SearchController(
|
public SearchController(
|
||||||
IOrchardServices services,
|
IOrchardServices services,
|
||||||
ISearchService searchService,
|
ISearchService searchService,
|
||||||
IContentManager contentManager) {
|
IContentManager contentManager,
|
||||||
|
IShapeFactory shapeFactory) {
|
||||||
Services = services;
|
Services = services;
|
||||||
_searchService = searchService;
|
_searchService = searchService;
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
|
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
|
Shape = shapeFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IOrchardServices Services { get; set; }
|
private IOrchardServices Services { get; set; }
|
||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
dynamic Shape { get; set; }
|
||||||
|
|
||||||
protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
|
protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
|
||||||
|
|
||||||
public ActionResult Index(string q, int page = 1, int pageSize = 10) {
|
public ActionResult Index(string q, Pager pager) {
|
||||||
var searchFields = CurrentSite.As<SearchSettingsPart>().SearchedFields;
|
var searchFields = CurrentSite.As<SearchSettingsPart>().SearchedFields;
|
||||||
|
|
||||||
IPageOfItems<ISearchHit> searchHits;
|
IPageOfItems<ISearchHit> searchHits;
|
||||||
@@ -46,38 +50,33 @@ namespace Orchard.Search.Controllers {
|
|||||||
Services.Notifier.Error(T("'*' or '?' not allowed as first character in WildcardQuery"));
|
Services.Notifier.Error(T("'*' or '?' not allowed as first character in WildcardQuery"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
searchHits = _searchService.Query(q, page, pageSize,
|
searchHits = _searchService.Query(q, pager.Page, pager.PageSize,
|
||||||
CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
|
CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
|
||||||
searchFields,
|
searchFields,
|
||||||
searchHit => searchHit);
|
searchHit => searchHit);
|
||||||
}
|
}
|
||||||
|
|
||||||
var searchResultViewModels = new List<SearchResultViewModel>();
|
var list = Shape.List();
|
||||||
|
foreach (var contentItem in searchHits.Select(searchHit => _contentManager.Get(searchHit.ContentItemId))) {
|
||||||
foreach(var searchHit in searchHits) {
|
|
||||||
var contentItem = _contentManager.Get(searchHit.ContentItemId);
|
|
||||||
// ignore search results which content item has been removed or unpublished
|
// ignore search results which content item has been removed or unpublished
|
||||||
if(contentItem == null){
|
if(contentItem == null){
|
||||||
searchHits.TotalItemCount--;
|
searchHits.TotalItemCount--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchResultViewModels.Add(new SearchResultViewModel {
|
list.Add(_contentManager.BuildDisplay(contentItem, "Summary"));
|
||||||
Content = _contentManager.BuildDisplay(contentItem, "SummaryForSearch"),
|
|
||||||
SearchHit = searchHit
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pageOfItems = new PageOfItems<SearchResultViewModel>(searchResultViewModels) {
|
var hasNextPage = searchHits.TotalPageCount > pager.Page;
|
||||||
PageNumber = page,
|
var pagerShape = Shape.Pager(pager).HasNextPage(hasNextPage);
|
||||||
PageSize = searchHits.PageSize,
|
|
||||||
TotalItemCount = searchHits.TotalItemCount
|
|
||||||
};
|
|
||||||
|
|
||||||
var searchViewModel = new SearchViewModel {
|
var searchViewModel = new SearchViewModel {
|
||||||
Query = q,
|
Query = q,
|
||||||
DefaultPageSize = 10, // TODO: sebastien <- yeah, I know :|
|
TotalItemCount = searchHits.TotalItemCount,
|
||||||
PageOfResults = pageOfItems
|
StartPosition = (pager.Page - 1) * pager.PageSize + 1,
|
||||||
|
EndPosition = pager.Page * pager.PageSize > searchHits.TotalItemCount ? searchHits.TotalItemCount : pager.Page * pager.PageSize,
|
||||||
|
ContentItems = list,
|
||||||
|
Pager = pagerShape
|
||||||
};
|
};
|
||||||
|
|
||||||
//todo: deal with page requests beyond result count
|
//todo: deal with page requests beyond result count
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using Orchard.Collections;
|
namespace Orchard.Search.ViewModels {
|
||||||
|
|
||||||
namespace Orchard.Search.ViewModels {
|
|
||||||
public class SearchViewModel {
|
public class SearchViewModel {
|
||||||
public string Query { get; set; }
|
public string Query { get; set; }
|
||||||
public int DefaultPageSize { get; set; }
|
public int TotalItemCount { get; set; }
|
||||||
public IPageOfItems<SearchResultViewModel> PageOfResults { get; set; }
|
public int StartPosition { get; set; }
|
||||||
|
public int EndPosition { get; set; }
|
||||||
|
public dynamic ContentItems { get; set; }
|
||||||
|
public dynamic Pager { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,26 @@
|
|||||||
@model Orchard.Search.ViewModels.SearchViewModel
|
@model Orchard.Search.ViewModels.SearchViewModel
|
||||||
@{ Style.Require("Search"); }
|
@{
|
||||||
|
Style.Require("Search");
|
||||||
|
|
||||||
|
IEnumerable<object> searchResults = Model.ContentItems;
|
||||||
|
Model.ContentItems.Classes.Add("content-items");
|
||||||
|
Model.ContentItems.Classes.Add("search-results");
|
||||||
|
}
|
||||||
<h1>@Html.TitleForPage(T("Search").Text)</h1>
|
<h1>@Html.TitleForPage(T("Search").Text)</h1>
|
||||||
|
@using(Html.BeginForm("index", "search", new { area = "Orchard.Search" }, FormMethod.Get, new { @class = "search group" })) {
|
||||||
@using(Html.BeginForm("index", "search", new { area = "Orchard.Search" }, FormMethod.Get, new { @class = "search" })) {
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@Html.TextBox("q", Model.Query)
|
@Html.TextBox("q", Model.Query)
|
||||||
<button type="submit">@T("Search")</button>
|
<button type="submit">@T("Search")</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
}
|
}
|
||||||
|
@if (HasText(Model.Query)) {
|
||||||
@if (!string.IsNullOrWhiteSpace(Model.Query)) {
|
if (searchResults.Count() == 0) {
|
||||||
if (Model.PageOfResults.Count() == 0) {
|
<p class="search-summary">@T.Plural("the <em>one</em> result", "<em>zero</em> results", searchResults.Count())</p>
|
||||||
<p class="search-summary">@T.Plural("the <em>one</em> result", "<em>zero</em> results", Model.PageOfResults.Count())</p>
|
|
||||||
} else {
|
} else {
|
||||||
<p class="search-summary">@T.Plural("the <em>one</em> result", "<em>{1} - {2}</em> of <em>{0}</em> results", Model.PageOfResults.TotalItemCount, Model.PageOfResults.StartPosition, Model.PageOfResults.EndPosition)</p>
|
<p class="search-summary">@T.Plural("the <em>one</em> result", "<em>{1} - {2}</em> of <em>{0}</em> results", Model.TotalItemCount, Model.StartPosition, Model.EndPosition)</p>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@if (Model.PageOfResults != null && Model.PageOfResults.Count() > 0) {
|
@if (searchResults != null && searchResults.Count() > 0) {
|
||||||
@Html.UnorderedList(Model.PageOfResults.Where(hit => hit.Content != null), (r, i) => Display(r.Content), "search-results contentItems")
|
@Display(searchResults)
|
||||||
@Html.Pager(Model.PageOfResults, Model.PageOfResults.PageNumber, Model.DefaultPageSize, new {q = Model.Query})
|
@Display(Model.Pager)
|
||||||
}
|
}
|
||||||
@@ -343,11 +343,6 @@ nav ul
|
|||||||
.blog-post-title {}
|
.blog-post-title {}
|
||||||
.meta {}
|
.meta {}
|
||||||
|
|
||||||
.blog-pagination { list-style: none; padding: 0; margin: 12px 0 0 0; }
|
|
||||||
.blog-pagination li { float: left; padding: 0 12px 0 0; margin: 0; }
|
|
||||||
.blog-pagination a { font-size: 1.077em; display: block; background-color: #dbdbdb; padding: 6px 6px; color: #434343;}
|
|
||||||
.blog-pagination a:hover { background-color: #434343; color: #fff; }
|
|
||||||
|
|
||||||
/* Comments */
|
/* Comments */
|
||||||
#comments { margin: 24px 0 0 0; padding: 0; }
|
#comments { margin: 24px 0 0 0; padding: 0; }
|
||||||
.comment-form { margin: 24px 0 0 0; padding: 0; }
|
.comment-form { margin: 24px 0 0 0; padding: 0; }
|
||||||
@@ -491,6 +486,16 @@ nav ul
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Pager
|
||||||
|
***************************************************************/
|
||||||
|
|
||||||
|
.pager { list-style: none; padding: 0; margin: 12px 0 0 0; }
|
||||||
|
.pager li { float: left; padding: 0 12px 0 0; margin: 0; }
|
||||||
|
.pager a { font-size: 1.077em; display: block; background-color: #dbdbdb; padding: 6px 6px; color: #434343;}
|
||||||
|
.pager a:hover { background-color: #434343; color: #fff; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Misc
|
/* Misc
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,7 @@
|
|||||||
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
||||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||||
<Compile Include="UI\FlatPositionComparer.cs" />
|
<Compile Include="UI\FlatPositionComparer.cs" />
|
||||||
|
<Compile Include="UI\Navigation\Pager.cs" />
|
||||||
<Compile Include="UI\Resources\IResourceManifestProvider.cs" />
|
<Compile Include="UI\Resources\IResourceManifestProvider.cs" />
|
||||||
<Compile Include="UI\Resources\ResourceManifestBuilder.cs" />
|
<Compile Include="UI\Resources\ResourceManifestBuilder.cs" />
|
||||||
<Compile Include="UI\Widgets\IRuleManager.cs" />
|
<Compile Include="UI\Widgets\IRuleManager.cs" />
|
||||||
|
|||||||
22
src/Orchard/UI/Navigation/Pager.cs
Normal file
22
src/Orchard/UI/Navigation/Pager.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace Orchard.UI.Navigation {
|
||||||
|
public class Pager {
|
||||||
|
private const int PageDefault = 1;
|
||||||
|
private const int PageSizeDefault = 10;
|
||||||
|
private int _pageSize;
|
||||||
|
private int _size;
|
||||||
|
|
||||||
|
public int Page {
|
||||||
|
get { return _pageSize > 0 ? _pageSize : PageDefault; }
|
||||||
|
set { _pageSize = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int PageSize {
|
||||||
|
get { return _size > 0 ? _size : PageSizeDefault; }
|
||||||
|
set { _size = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetStartIndex(int? page = null) {
|
||||||
|
return ((page ?? Page) - 1)*PageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user