--HG--
branch : dev
This commit is contained in:
Michael Dorian Bach
2010-10-13 19:23:33 -07:00
20 changed files with 244 additions and 109 deletions

View File

@@ -33,14 +33,15 @@ namespace Orchard.Blogs {
item =>
item.Action("Item", "BlogAdmin", new {area = "Orchard.Blogs", blogSlug = singleBlog.Slug}).Permission(Permissions.MetaListBlogs));
menu.Add(T("Create New Blog"), "1.1",
item =>
item.Action("Create", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.ManageBlogs));
if (singleBlog != null)
menu.Add(T("Create New Post"), "1.2",
if ( singleBlog != null )
menu.Add(T("Create New Post"), "1.1",
item =>
item.Action("Create", "BlogPostAdmin", new {area = "Orchard.Blogs", blogSlug = singleBlog.Slug}).Permission(Permissions.PublishBlogPost));
item.Action("Create", "BlogPostAdmin", new { area = "Orchard.Blogs", blogSlug = singleBlog.Slug }).Permission(Permissions.PublishBlogPost));
menu.Add(T("Create New Blog"), "1.2",
item =>
item.Action("Create", "BlogAdmin", new { area = "Orchard.Blogs" }).Permission(Permissions.ManageBlogs));
}
}
}

View File

@@ -1,3 +1,4 @@
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
@@ -6,6 +7,7 @@ using System.Xml.Linq;
using Orchard.Blogs.Models;
using Orchard.Blogs.Routing;
using Orchard.Blogs.Services;
using Orchard.Blogs.ViewModels;
using Orchard.DisplayManagement;
using Orchard.Logging;
using Orchard.Mvc.Results;
@@ -16,12 +18,14 @@ namespace Orchard.Blogs.Controllers {
public class BlogController : Controller {
private readonly IOrchardServices _services;
private readonly IBlogService _blogService;
private readonly IBlogPostService _blogPostService;
private readonly IBlogSlugConstraint _blogSlugConstraint;
private readonly RouteCollection _routeCollection;
public BlogController(IOrchardServices services, IBlogService blogService, IBlogSlugConstraint blogSlugConstraint, RouteCollection routeCollection, IShapeHelperFactory shapeHelperFactory) {
public BlogController(IOrchardServices services, IBlogService blogService, IBlogPostService blogPostService, IBlogSlugConstraint blogSlugConstraint, RouteCollection routeCollection, IShapeHelperFactory shapeHelperFactory) {
_services = services;
_blogService = blogService;
_blogPostService = blogPostService;
_blogSlugConstraint = blogSlugConstraint;
_routeCollection = routeCollection;
Logger = NullLogger.Instance;
@@ -44,18 +48,31 @@ namespace Orchard.Blogs.Controllers {
}
//TODO: (erikpo) Should move the slug parameter and get call and null check up into a model binder
public ActionResult Item(string blogSlug) {
public ActionResult Item(string blogSlug, int page) {
const int pageSize = 10;
var correctedSlug = _blogSlugConstraint.FindSlug(blogSlug);
if (correctedSlug == null)
return new NotFoundResult();
var blog = _blogService.Get(correctedSlug);
BlogPart blog = _blogService.Get(correctedSlug);
if (blog == null)
return new NotFoundResult();
//todo: (heskew) "Blog" should be an alternative instead of a display type
var model = _services.ContentManager.BuildDisplay(blog, "Blog");
var blogPosts = _blogPostService.Get(blog, (page - 1)*pageSize, pageSize).Select(b => _services.ContentManager.BuildDisplay(b, "Summary.BlogPost"));
var list = Shape.List();
list.AddRange(blogPosts);
var model = new DisplayBlogViewModel {
BlogPostList = list,
BlogPart = blog,
Page = page,
PageSize = pageSize
};
return View(model);
}
public ActionResult LiveWriterManifest(string blogSlug) {

View File

@@ -107,6 +107,7 @@
<Compile Include="Services\IBlogService.cs" />
<Compile Include="Services\XmlRpcHandler.cs" />
<Compile Include="ViewModels\BlogPostArchiveViewModel.cs" />
<Compile Include="ViewModels\DisplayBlogViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Admin\images\draft.gif" />
@@ -118,6 +119,7 @@
<Content Include="Scripts\archives.js" />
<Content Include="Styles\admin.css" />
<Content Include="Styles\archives.css" />
<Content Include="Styles\pagination.css" />
<Content Include="Views\BlogAdmin\Create.cshtml" />
<Content Include="Views\BlogAdmin\Edit.cshtml" />
<Content Include="Views\BlogAdmin\Item.cshtml" />
@@ -131,7 +133,6 @@
<Content Include="Views\Parts\Blogs.Blog.Manage.cshtml" />
<Content Include="Views\Parts\Blogs.Blog.Description.cshtml" />
<Content Include="Views\Parts\Common.Metadata.Admin.Blog.cshtml" />
<Content Include="Views\Parts\Blogs.BlogPost.List.cshtml" />
<Content Include="Views\EditorTemplates\Parts\Blogs.Blog.Fields.cshtml" />
<Content Include="Views\Parts\Blogs.BlogPost.List.Admin.cshtml">
<SubType>Code</SubType>
@@ -190,6 +191,7 @@
<None Include="Views\DisplayTemplates\Parts\Blogs.BlogArchives.cshtml" />
<None Include="Views\EditorTemplates\Parts\Blogs.RecentBlogPosts.cshtml" />
<None Include="Views\EditorTemplates\Parts\Blogs.BlogArchives.cshtml" />
<None Include="Views\Parts\Blogs.BlogPost.List.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -259,6 +259,24 @@ namespace Orchard.Blogs {
Priority = 11,
Route = new Route(
"{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 {
{"area", "Orchard.Blogs"},
{"controller", "Blog"},

View File

@@ -49,6 +49,11 @@ namespace Orchard.Blogs.Services {
return GetBlogQuery(blogPart, versionOptions).List().Select(ci => ci.As<BlogPostPart>());
}
public IEnumerable<BlogPostPart> Get(BlogPart blogPart, int skip, int count) {
return GetBlogQuery(blogPart, VersionOptions.Published).Slice(skip, count).ToList().Select(ci => ci.As<BlogPostPart>());
}
public IEnumerable<BlogPostPart> Get(BlogPart blogPart, ArchiveData archiveData) {
var query = GetBlogQuery(blogPart, VersionOptions.Published);

View File

@@ -12,6 +12,7 @@ namespace Orchard.Blogs.Services {
IEnumerable<BlogPostPart> Get(BlogPart blogPart);
IEnumerable<BlogPostPart> Get(BlogPart blogPart, VersionOptions versionOptions);
IEnumerable<BlogPostPart> Get(BlogPart blogPart, ArchiveData archiveData);
IEnumerable<BlogPostPart> Get(BlogPart blogPart, int skip, int count);
IEnumerable<KeyValuePair<ArchiveData, int>> GetArchives(BlogPart blogPart);
void Delete(BlogPostPart blogPostPart);
void Publish(BlogPostPart blogPostPart);

View File

@@ -1,3 +1,3 @@
#main .blog-description p {
margin-bottom:1em;
}
}

View File

@@ -0,0 +1,19 @@
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;
}

View File

@@ -0,0 +1,10 @@
using Orchard.Blogs.Models;
namespace Orchard.Blogs.ViewModels {
public class DisplayBlogViewModel {
public BlogPart BlogPart { get; set; }
public dynamic BlogPostList { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
}
}

View File

@@ -1 +1,28 @@
@Display(Model)
@model Orchard.Blogs.ViewModels.DisplayBlogViewModel
@using Orchard.Blogs.Extensions;
@{
Style.Include("pagination.css");
}
@if (Model.BlogPostList.Items.Count > 0) {
@Display(Model.BlogPostList)
<ul class="pagination">
@if(Model.BlogPostList.Items.Count == Model.PageSize) {
<li class="older">
@Html.ActionLink(T("Older Posts").Text, "Item", new { Area = "Orchard.Blogs", blogSlug = Model.BlogPart.Slug, 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.BlogPart.Slug, page = Model.Page - 1 })
</li>
}
</ul>
}
else {
<p>@T("There are no posts for this blog.")</p>
}

View File

@@ -5,4 +5,4 @@
@using Orchard.Core.Common.ViewModels;
<h2>@Html.Link((string)Model.Title, Url.BlogPost((BlogPostPart)Model.ContentItem.Get(typeof(BlogPostPart))))</h2>
<div class="meta">@Html.PublishedState(new CommonMetadataViewModel((CommonPart)Model.ContentItem.Get(typeof(CommonPart))), T) | @Display(Model.meta)</div>
<div class="content">@Display(Model.Primary)</div>
<div class="content">@Display(Model.Primary)</div>

View File

@@ -54,7 +54,7 @@ namespace Orchard.Search.Controllers {
var searchViewModel = new SearchViewModel {
Query = q,
DefaultPageSize = 10, // <- yeah, I know :|
DefaultPageSize = 10, // TODO: sebastien <- yeah, I know :|
PageOfResults = pageOfItems
};

View File

@@ -24,7 +24,7 @@ namespace Orchard.Search {
.WithSetting("Stereotype", "Widget")
);
return 5;
return 2;
}
}
}

View File

@@ -2,7 +2,7 @@
namespace Orchard.Search.Models {
/// <summary>
/// Cotnent part for the search form widget
/// Content part for the search form widget
/// </summary>
public class SearchFormPart : ContentPart {
}

View File

@@ -81,6 +81,13 @@ namespace Orchard.Setup.Controllers {
ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match").ToString());
}
if(!model.DatabaseOptions && !String.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) {
model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim();
if(!Char.IsLetter(model.DatabaseTablePrefix[0])) {
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter").Text);
}
}
ValidateMachineKey();
if (!ModelState.IsValid) {

View File

@@ -118,6 +118,11 @@
<Name>Orchard.Framework</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Views\Items\User.Editor.cshtml">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -0,0 +1,8 @@
<div class="sections">
<div class="primary">
@Display(Model.Primary)
</div>
<div class="secondary">
@Display(Model.Secondary)
</div>
</div>

View File

@@ -106,7 +106,7 @@ namespace Orchard.Widgets.Controllers {
}
catch (Exception exception) {
Services.Notifier.Error(T("Creating widget failed: {0}", exception.Message));
return RedirectToAction("Index");
return RedirectToAction("Index", "Admin", new { id = layerId });
}
}
@@ -128,12 +128,12 @@ namespace Orchard.Widgets.Controllers {
}
Services.Notifier.Information(T("Your {0} has been created.", widgetPart.TypeDefinition.DisplayName));
return RedirectToAction("Index");
}
catch (Exception exception) {
Services.Notifier.Error(T("Creating widget failed: {0}", exception.Message));
return RedirectToAction("Index");
}
return RedirectToAction("Index", "Admin", new { id = layerId });
}
public ActionResult AddLayer() {
@@ -171,7 +171,7 @@ namespace Orchard.Widgets.Controllers {
}
Services.Notifier.Information(T("Your {0} has been created.", layerPart.TypeDefinition.DisplayName));
return RedirectToAction("Index");
return RedirectToAction("Index", "Admin", new { id = layerPart.Id });
}
catch (Exception exception) {
Services.Notifier.Error(T("Creating layer failed: {0}", exception.Message));
@@ -194,7 +194,7 @@ namespace Orchard.Widgets.Controllers {
}
catch (Exception exception) {
Services.Notifier.Error(T("Editing layer failed: {0}", exception.Message));
return RedirectToAction("Index");
return RedirectToAction("Index", "Admin", new { id });
}
}
@@ -216,12 +216,12 @@ namespace Orchard.Widgets.Controllers {
}
Services.Notifier.Information(T("Your {0} has been saved.", layerPart.TypeDefinition.DisplayName));
return RedirectToAction("Index");
}
catch (Exception exception) {
Services.Notifier.Error(T("Editing layer failed: {0}", exception.Message));
return RedirectToAction("Index");
}
return RedirectToAction("Index", "Admin", new { id });
}
[HttpPost, ActionName("EditLayer")]
@@ -238,15 +238,16 @@ namespace Orchard.Widgets.Controllers {
Services.Notifier.Error(T("Removing Layer failed: {0}", exception.Message));
}
return RedirectToAction("Index");
return RedirectToAction("Index", "Admin", new { id });
}
public ActionResult EditWidget(int id) {
if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel)))
return new HttpUnauthorizedResult();
WidgetPart widgetPart = null;
try {
WidgetPart widgetPart = _widgetsService.GetWidget(id);
widgetPart = _widgetsService.GetWidget(id);
if (widgetPart == null) {
Services.Notifier.Error(T("Widget not found: {1}", id));
return RedirectToAction("Index");
@@ -257,6 +258,10 @@ namespace Orchard.Widgets.Controllers {
}
catch (Exception exception) {
Services.Notifier.Error(T("Editing widget failed: {0}", exception.Message));
if (widgetPart != null)
return RedirectToAction("Index", "Admin", new { id = widgetPart.LayerPart.Id });
return RedirectToAction("Index");
}
}
@@ -267,11 +272,12 @@ namespace Orchard.Widgets.Controllers {
if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel)))
return new HttpUnauthorizedResult();
WidgetPart widgetPart = null;
try {
WidgetPart widgetPart = _widgetsService.GetWidget(id);
widgetPart = _widgetsService.GetWidget(id);
if (widgetPart == null)
return new NotFoundResult();
var model = Services.ContentManager.UpdateEditor(widgetPart, this);
if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
@@ -279,12 +285,14 @@ namespace Orchard.Widgets.Controllers {
}
Services.Notifier.Information(T("Your {0} has been saved.", widgetPart.TypeDefinition.DisplayName));
return RedirectToAction("Index");
}
catch (Exception exception) {
Services.Notifier.Error(T("Editing widget failed: {0}", exception.Message));
return RedirectToAction("Index");
}
return widgetPart != null ?
RedirectToAction("Index", "Admin", new { id = widgetPart.LayerPart.Id }) :
RedirectToAction("Index");
}
[HttpPost, ActionName("EditWidget")]
@@ -293,15 +301,22 @@ namespace Orchard.Widgets.Controllers {
if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel)))
return new HttpUnauthorizedResult();
WidgetPart widgetPart = null;
try {
_widgetsService.DeleteWidget(id);
widgetPart = _widgetsService.GetWidget(id);
if (widgetPart == null)
return new NotFoundResult();
_widgetsService.DeleteWidget(widgetPart.Id);
Services.Notifier.Information(T("Widget was successfully deleted"));
}
catch (Exception exception) {
Services.Notifier.Error(T("Removing Widget failed: {0}", exception.Message));
}
return RedirectToAction("Index");
return widgetPart != null ?
RedirectToAction("Index", "Admin", new { id = widgetPart.LayerPart.Id }) :
RedirectToAction("Index");
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {

View File

@@ -11,83 +11,83 @@
Html.ValidationSummary();
<div id="widgets">
<div class="widgets-availableWidgets">
<h2>Available Widgets</h2>
<div id="widgets">
<fieldset>
<table class="items" summary="@T("This is a table of the widgets currently available for use in your application.")">
<colgroup>
<col id="Col1" />
<col id="Col2" />
</colgroup>
<thead>
<tr>
<th scope="col">@T("Name")</th>
<th scope="col"></th>
</tr>
</thead>
@foreach (string widget in Model.WidgetTypes) {
<tr>
<td>@widget</td>
<td>@Html.ActionLink(T("Add").ToString(), "AddWidget", new { layerId = Model.CurrentLayer.Id, widgetType = widget })</td>
</tr>
}
</table>
<div class="widgets-availableWidgets">
<h2>Available Widgets</h2>
</fieldset>
</div>
<fieldset>
<table class="items" summary="@T("This is a table of the widgets currently available for use in your application.")">
<colgroup>
<col id="Col1" />
<col id="Col2" />
</colgroup>
<thead>
<tr>
<th scope="col">@T("Name")</th>
<th scope="col"></th>
</tr>
</thead>
@foreach (string widget in Model.WidgetTypes) {
<tr>
<td>@widget</td>
<td>@Html.ActionLink(T("Add").ToString(), "AddWidget", new { layerId = Model.CurrentLayer.Id, widgetType = widget })</td>
</tr>
}
</table>
<div class="widgets-availableLayers">
<h2>Widget Zones</h2>
</fieldset>
</div>
<fieldset>
<div>
<ul class="widgets-layerZones">
@foreach (string zone in Model.Zones) {
<li>
<div class="widgets-zone">@zone</div>
<ul>
@foreach (WidgetPart widget in Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).OrderBy(widgetPart => widgetPart.Position, new Orchard.UI.FlatPositionComparer())) {
<li class="widgets-zoneWidget">
@if (widget.Position != "1") {
<input type="image" name="submit.MoveUp.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/moveup.gif")" alt="Move up" value="@widget.Id" />
}
@if (int.Parse(widget.Position) < Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).Count()) {
<input type="image" name="submit.MoveDown.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/movedown.gif")" alt="Move down" value="@widget.Id" />
}
@Html.ActionLink(@widget.Title, "EditWidget", new { @widget.Id })
</li>
}
</ul>
</li>
}
</ul>
</div>
<div class="widgets-availableLayers">
<h2>Widget Zones</h2>
<div class="widgets-layers">
<ul>
@foreach (var layer in Model.Layers) {
if (layer.Id == Model.CurrentLayer.Id) {
<li class="widgets-currentLayer widgets-editLayer">
@Html.ActionLink(@layer.Name, "Index", new { @layer.Id })
<a href="@Url.Action("EditLayer", new { @layer.Id })">
<img width="15" height="15" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/edit.gif")" />
</a>
</li>
} else {
<li class="widgets-editLayer">
@Html.ActionLink(@layer.Name, "Index", new { @layer.Id })
<a href="@Url.Action("EditLayer", new { @layer.Id })">
<img width="15" height="15" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/edit.gif")" />
</a>
</li>
}
}
<ul>
</div>
</fieldset>
</div>
</div>
<fieldset>
<div>
<ul class="widgets-layerZones">
@foreach (string zone in Model.Zones) {
<li>
<div class="widgets-zone">@zone</div>
<ul>
@foreach (WidgetPart widget in Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).OrderBy(widgetPart => widgetPart.Position, new Orchard.UI.FlatPositionComparer())) {
<li class="widgets-zoneWidget">
@if (widget.Position != "1") {
<input type="image" name="submit.MoveUp.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/moveup.gif")" alt="Move up" value="@widget.Id" />
}
@if (int.Parse(widget.Position) < Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).Count()) {
<input type="image" name="submit.MoveDown.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/movedown.gif")" alt="Move down" value="@widget.Id" />
}
@Html.ActionLink(@widget.Title, "EditWidget", new { @widget.Id })
</li>
}
</ul>
</li>
}
</ul>
</div>
<div class="widgets-layers">
<ul>
@foreach (var layer in Model.Layers) {
if (layer.Id == Model.CurrentLayer.Id) {
<li class="widgets-currentLayer widgets-editLayer">
@Html.ActionLink(@layer.Name, "Index", new { @layer.Id })
<a href="@Url.Action("EditLayer", new { @layer.Id })">
<img width="15" height="15" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/edit.gif")" />
</a>
</li>
} else {
<li class="widgets-editLayer">
@Html.ActionLink(@layer.Name, "Index", new { @layer.Id })
<a href="@Url.Action("EditLayer", new { @layer.Id })">
<img width="15" height="15" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/edit.gif")" />
</a>
</li>
}
}
<ul>
</div>
</fieldset>
</div>
</div>
}

View File

@@ -9,7 +9,7 @@ namespace Orchard.UI.Resources {
manifest.DefineScript("jQueryUI_Core").SetUrl("jquery.ui.core.js").SetVersion("1.8b1").SetDependencies("jQuery");
manifest.DefineScript("jQueryUI_Widget").SetUrl("jquery.ui.widget.js").SetVersion("1.8b1").SetDependencies("jQuery");
manifest.DefineScript("jQueryUI_DatePicker").SetUrl("jquery.ui.datepicker.js").SetVersion("1.8b1").SetDependencies("jQueryUI_Core", "jQueryUI_Widget");
manifest.DefineScript("jQueryUtils_TimePicker").SetUrl("ui.timepickr.js").SetVersion("0.7.0a").SetDependencies("jQueryUtils", "jQueryUI_Core");
manifest.DefineScript("jQueryUtils_TimePicker").SetUrl("ui.timepickr.js").SetVersion("0.7.0a").SetDependencies("jQueryUtils", "jQueryUI_Core", "jQueryUI_Widget");
manifest.DefineStyle("jQueryUtils_TimePicker").SetUrl("ui.timepickr.css");
manifest.DefineStyle("jQueryUI_Orchard").SetUrl("jquery-ui-1.7.2.custom.css").SetVersion("1.7.2");