From c44ca04676c20b30b20e960f3fd7c41d790cab8b Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Thu, 10 Mar 2011 11:17:04 -0800 Subject: [PATCH 1/5] Deleting media files was broke. And when it failed, it double failed with a NullReferenceException while redirecting you. --HG-- branch : dev --- .../Modules/Orchard.Media/Controllers/AdminController.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs index 0900b34bc..041cfb9ce 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs @@ -102,7 +102,7 @@ namespace Orchard.Media.Controllers { string folderName = input[fileName]; if (!Services.Authorizer.Authorize(Permissions.ManageMedia, T("Couldn't delete media file"))) return new HttpUnauthorizedResult(); - _mediaService.DeleteFile(fileName, folderName); + _mediaService.DeleteFile(folderName, fileName); Services.Notifier.Information(T("Media file deleted")); } @@ -119,8 +119,7 @@ namespace Orchard.Media.Controllers { return RedirectToAction("Index"); } catch (Exception exception) { this.Error(exception, T("Deleting failed: {0}", exception.Message), Logger, Services.Notifier); - - return View(); + return RedirectToAction("Index"); } } From 9fae6c83a74ea127f3fae481d5002a773d4f1b04 Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Thu, 10 Mar 2011 11:22:17 -0800 Subject: [PATCH 2/5] Renaming 'Remove' actions to 'Delete' across the admin, except when 'removing' parts or fields from a content type, where 'remove' is more appropriate. --HG-- branch : dev --- src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml | 2 +- .../Core/Contents/Views/Content.SummaryAdmin.cshtml | 2 +- src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml | 2 +- .../Modules/Orchard.Blogs/Views/BlogAdmin/List.cshtml | 2 +- .../Orchard.Blogs/Views/Parts.Blogs.BlogPost.ListAdmin.cshtml | 2 +- .../Modules/Orchard.Comments/Views/Admin/Details.cshtml | 2 +- .../Modules/Orchard.Comments/Views/Admin/Index.cshtml | 4 ++-- src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Edit.cshtml | 2 +- .../Modules/Orchard.Media/Views/Admin/EditProperties.cshtml | 2 +- .../Modules/Orchard.Media/Views/Admin/Index.cshtml | 2 +- .../Modules/Orchard.Packaging/Views/Gallery/Sources.cshtml | 2 +- src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Edit.cshtml | 2 +- .../Modules/Orchard.Roles/Views/Admin/Index.cshtml | 4 ++-- src/Orchard.Web/Modules/Orchard.Tags/Views/Admin/Index.cshtml | 4 ++-- .../Modules/Orchard.Users/Views/Admin/Index.cshtml | 4 ++-- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml b/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml index d838df9e1..1f564da6a 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml +++ b/src/Orchard.Web/Core/Contents/Views/Admin/List.cshtml @@ -21,7 +21,7 @@ @Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.None, T("Choose action...").ToString()) @Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.PublishNow, T("Publish Now").ToString()) @Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.Unpublish, T("Unpublish").ToString()) - @Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.Remove, T("Remove").ToString()) + @Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.Remove, T("Delete").ToString()) diff --git a/src/Orchard.Web/Core/Contents/Views/Content.SummaryAdmin.cshtml b/src/Orchard.Web/Core/Contents/Views/Content.SummaryAdmin.cshtml index 9e9e42930..6db74edc4 100644 --- a/src/Orchard.Web/Core/Contents/Views/Content.SummaryAdmin.cshtml +++ b/src/Orchard.Web/Core/Contents/Views/Content.SummaryAdmin.cshtml @@ -18,7 +18,7 @@ @if (Model.Content != null) {
@Display(Model.Content)
diff --git a/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml b/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml index 015cbe101..51c088158 100644 --- a/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml @@ -29,7 +29,7 @@ @if (!menuPartEntry.IsMenuItem) { } else {} - @T("Remove") + @T("Delete") ++menuPartEntryIndex; } diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/List.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/List.cshtml index e12fc5251..7ba2b209f 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/List.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/List.cshtml @@ -11,7 +11,7 @@ @Html.Hidden("returnUrl", ViewContext.RequestContext.HttpContext.Request.ToUrlString()) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Parts.Blogs.BlogPost.ListAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Parts.Blogs.BlogPost.ListAdmin.cshtml index 80ff6fefa..11dcb60e6 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Parts.Blogs.BlogPost.ListAdmin.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Parts.Blogs.BlogPost.ListAdmin.cshtml @@ -8,7 +8,7 @@ @Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.None, T("Choose action...").ToString()) @Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.PublishNow, T("Publish Now").ToString()) @Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.Unpublish, T("Unpublish").ToString()) - @Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.Remove, T("Remove").ToString()) + @Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.Remove, T("Delete").ToString()) @Html.Hidden("returnUrl", ViewContext.RequestContext.HttpContext.Request.ToUrlString()) diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Details.cshtml b/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Details.cshtml index 58bffb2b7..990ad322f 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Details.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Details.cshtml @@ -28,7 +28,7 @@ @Html.SelectOption(Model.Options.BulkAction, CommentDetailsBulkAction.Approve, T("Approve").ToString()) @Html.SelectOption(Model.Options.BulkAction, CommentDetailsBulkAction.Unapprove, T("Unapprove").ToString()) @Html.SelectOption(Model.Options.BulkAction, CommentDetailsBulkAction.MarkAsSpam, T("Mark as Spam").ToString()) - @Html.SelectOption(Model.Options.BulkAction, CommentDetailsBulkAction.Delete, T("Remove").ToString()) + @Html.SelectOption(Model.Options.BulkAction, CommentDetailsBulkAction.Delete, T("Delete").ToString()) diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml index e91b9ca35..f0653d1ef 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Comments/Views/Admin/Index.cshtml @@ -19,7 +19,7 @@ @Html.SelectOption(Model.Options.BulkAction, CommentIndexBulkAction.Approve, T("Approve").ToString()) @Html.SelectOption(Model.Options.BulkAction, CommentIndexBulkAction.Unapprove, T("Unapprove").ToString()) @Html.SelectOption(Model.Options.BulkAction, CommentIndexBulkAction.MarkAsSpam, T("Mark as Spam").ToString()) - @Html.SelectOption(Model.Options.BulkAction, CommentIndexBulkAction.Delete, T("Remove").ToString()) + @Html.SelectOption(Model.Options.BulkAction, CommentIndexBulkAction.Delete, T("Delete").ToString()) @@ -100,7 +100,7 @@ @("Unapprove")@T(" | ") } @T("Edit")@T(" | ") - @T("Remove") + @T("Delete") diff --git a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Edit.cshtml index 896c3ca24..1a6d28ebc 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Edit.cshtml @@ -24,7 +24,7 @@
diff --git a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditProperties.cshtml b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditProperties.cshtml index c217b2ddc..0517ef82d 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditProperties.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditProperties.cshtml @@ -24,6 +24,6 @@
- +
} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Index.cshtml index e5d9745c0..417bc4a34 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/Index.cshtml @@ -8,7 +8,7 @@
diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/Sources.cshtml b/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/Sources.cshtml index 6eafa0d2a..784cfda95 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/Sources.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Views/Gallery/Sources.cshtml @@ -24,7 +24,7 @@ @item.FeedTitle @Html.Link(item.FeedUrl, item.FeedUrl) - @Html.ActionLink(T("Remove").ToString(), "Remove", new { id = item.Id }) + @Html.ActionLink(T("Delete").ToString(), "Remove", new { id = item.Id }) } diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Edit.cshtml index 29d507c48..1e6981b6b 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Edit.cshtml @@ -60,7 +60,7 @@
@if (Model.Name != "Administrator") { - + }
} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Index.cshtml index 1ce22b86c..686bbe1a1 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Roles/Views/Admin/Index.cshtml @@ -12,7 +12,7 @@
@@ -39,7 +39,7 @@ @Html.ActionLink(T("Edit").ToString(), "Edit", new { row.Id }) @if (row.Name != "Administrator") { @T(" | ") - @T("Remove") + @T("Delete") } diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Tags/Views/Admin/Index.cshtml index e440dc34a..1e8df36df 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Tags/Views/Admin/Index.cshtml @@ -16,7 +16,7 @@ @@ -44,7 +44,7 @@ @Html.ActionLink(T("Edit").ToString(), "Edit", new {id = tagEntry.Tag.Id}) @T(" | ") - @T("Remove") + @T("Delete") tagIndex = tagIndex + 1; diff --git a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml index 6933bcca0..aa5bb6cac 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Index.cshtml @@ -19,7 +19,7 @@ @Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.Approve, T("Approve").ToString()) @Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.Disable, T("Disable").ToString()) @Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.ChallengeEmail, T("Send challenge E-mail").ToString()) - @Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.Delete, T("Remove").ToString()) + @Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.Delete, T("Delete").ToString()) @@ -69,7 +69,7 @@ @Html.ActionLink(T("Edit").ToString(), "Edit", new { entry.User.Id }) | - @Html.ActionLink(T("Remove").ToString(), "Delete", new { entry.User.Id }) | + @Html.ActionLink(T("Delete").ToString(), "Delete", new { entry.User.Id }) | @if (entry.User.RegistrationStatus == UserStatus.Pending) { @Html.ActionLink(T("Approve").ToString(), "Approve", new { entry.User.Id }) } else { From e0dada5fb0a4fa0fa42caab80fc361ed5b7d26bc Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Thu, 10 Mar 2011 11:38:43 -0800 Subject: [PATCH 3/5] Fixing ambiguous call in containable, containerwidget, and customproperties drivers. --HG-- branch : dev --- .../Core/Containers/Drivers/ContainablePartDriver.cs | 2 +- .../Core/Containers/Drivers/ContainerWidgetPartDriver.cs | 2 +- .../Core/Containers/Drivers/CustomPropertiesDriver.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Orchard.Web/Core/Containers/Drivers/ContainablePartDriver.cs b/src/Orchard.Web/Core/Containers/Drivers/ContainablePartDriver.cs index b17082671..cc00c1529 100644 --- a/src/Orchard.Web/Core/Containers/Drivers/ContainablePartDriver.cs +++ b/src/Orchard.Web/Core/Containers/Drivers/ContainablePartDriver.cs @@ -20,7 +20,7 @@ namespace Orchard.Core.Containers.Drivers { public Localizer T { get; set; } protected override DriverResult Editor(ContainablePart part, dynamic shapeHelper) { - return Editor(part, null, shapeHelper); + return Editor(part, (IUpdateModel)null, shapeHelper); } protected override DriverResult Editor(ContainablePart part, IUpdateModel updater, dynamic shapeHelper) { diff --git a/src/Orchard.Web/Core/Containers/Drivers/ContainerWidgetPartDriver.cs b/src/Orchard.Web/Core/Containers/Drivers/ContainerWidgetPartDriver.cs index fc107513c..be9f7bad6 100644 --- a/src/Orchard.Web/Core/Containers/Drivers/ContainerWidgetPartDriver.cs +++ b/src/Orchard.Web/Core/Containers/Drivers/ContainerWidgetPartDriver.cs @@ -49,7 +49,7 @@ namespace Orchard.Core.Containers.Drivers { } protected override DriverResult Editor(ContainerWidgetPart part, dynamic shapeHelper) { - return Editor(part, null, shapeHelper); + return Editor(part, (IUpdateModel)null, shapeHelper); } protected override DriverResult Editor(ContainerWidgetPart part, IUpdateModel updater, dynamic shapeHelper) { diff --git a/src/Orchard.Web/Core/Containers/Drivers/CustomPropertiesDriver.cs b/src/Orchard.Web/Core/Containers/Drivers/CustomPropertiesDriver.cs index 8a7bda0aa..4af33df4b 100644 --- a/src/Orchard.Web/Core/Containers/Drivers/CustomPropertiesDriver.cs +++ b/src/Orchard.Web/Core/Containers/Drivers/CustomPropertiesDriver.cs @@ -7,7 +7,7 @@ using Orchard.Data; namespace Orchard.Core.Containers.Drivers { public class CustomPropertiesPartDriver : ContentPartDriver { protected override DriverResult Editor(CustomPropertiesPart part, dynamic shapeHelper) { - return Editor(part, null, shapeHelper); + return Editor(part, (IUpdateModel)null, shapeHelper); } protected override DriverResult Editor(CustomPropertiesPart part, IUpdateModel updater, dynamic shapeHelper) { From 6c068e45efbef3d27d250fbeda3bb49ddc80d319 Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Thu, 10 Mar 2011 11:39:28 -0800 Subject: [PATCH 4/5] ContainersPathConstraintUpdater catches errors due to missing migrations. --HG-- branch : dev --- .../Services/ContainersPathConstraintUpdater.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Orchard.Web/Core/Containers/Services/ContainersPathConstraintUpdater.cs b/src/Orchard.Web/Core/Containers/Services/ContainersPathConstraintUpdater.cs index 5d2793447..18417ab72 100644 --- a/src/Orchard.Web/Core/Containers/Services/ContainersPathConstraintUpdater.cs +++ b/src/Orchard.Web/Core/Containers/Services/ContainersPathConstraintUpdater.cs @@ -1,9 +1,12 @@ -using System.Linq; +using System; +using System.Linq; using Orchard.ContentManagement; using Orchard.Core.Containers.Models; using Orchard.Core.Routable.Models; using Orchard.Environment; +using Orchard.Logging; using Orchard.Tasks; +using Orchard.UI.Admin; namespace Orchard.Core.Containers.Services { public class ContainersPathConstraintUpdater : IOrchardShellEvents, IBackgroundTask { @@ -13,8 +16,11 @@ namespace Orchard.Core.Containers.Services { public ContainersPathConstraintUpdater(IContainersPathConstraint containersPathConstraint, IContentManager contentManager) { _containersPathConstraint = containersPathConstraint; _contentManager = contentManager; + Logger = NullLogger.Instance; } + public ILogger Logger { get; set; } + void IOrchardShellEvents.Activated() { Refresh(); } @@ -27,8 +33,13 @@ namespace Orchard.Core.Containers.Services { } private void Refresh() { - var routeParts = _contentManager.Query().Join().List(); - _containersPathConstraint.SetPaths(routeParts.Select(x=>x.Path)); + try { + var routeParts = _contentManager.Query().Join().List(); + _containersPathConstraint.SetPaths(routeParts.Select(x => x.Path)); + } + catch (Exception ex) { + Logger.Error(ex, "Error while setting path constraints for containers."); + } } } } \ No newline at end of file From deb5513737455f822f9506ffc9df81123ed1ed6e Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Thu, 10 Mar 2011 11:45:07 -0800 Subject: [PATCH 5/5] Initial new List Management UI. --HG-- branch : dev --- .../Containers/Drivers/ContainerPartDriver.cs | 43 +-- src/Orchard.Web/Core/Containers/Migrations.cs | 5 + .../Core/Containers/Models/ContainerPart.cs | 1 + .../Core/Containers/Placement.info | 4 - .../ViewModels/ContainerViewModel.cs | 9 + .../Views/EditorTemplates/Container.cshtml | 36 +-- .../Contents/Controllers/AdminController.cs | 32 ++- .../ViewModels/ListContentsViewModel.cs | 1 - .../Views/Admin/CreatableTypeList.cshtml | 2 +- src/Orchard.Web/Core/Orchard.Core.csproj | 5 +- .../Controllers/AdminController.cs | 269 ++++++++++++++++++ .../Handlers/ContainerPartHandler.cs | 28 ++ .../Orchard.Lists/Orchard.Lists.csproj | 22 +- .../Modules/Orchard.Lists/Placement.info | 9 + .../Orchard.Lists}/Routes.cs | 24 +- .../Modules/Orchard.Lists/Scripts/Web.config | 21 ++ .../Scripts/orchard-lists-admin.js | 10 + .../ViewModels/ListContentsViewModel.cs | 53 ++++ .../Orchard.Lists/Views/Admin/List.cshtml | 64 +++++ ...ts.Container.Contained.SummaryAdmin.cshtml | 2 +- .../Views/Parts.Container.Manage.cshtml | 8 + 21 files changed, 573 insertions(+), 75 deletions(-) create mode 100644 src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/Handlers/ContainerPartHandler.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/Placement.info rename src/Orchard.Web/{Core/Contents => Modules/Orchard.Lists}/Routes.cs (76%) create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/Scripts/Web.config create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/Scripts/orchard-lists-admin.js create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/ViewModels/ListContentsViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/Views/Admin/List.cshtml rename src/Orchard.Web/{Core/Containers => Modules/Orchard.Lists}/Views/Parts.Container.Contained.SummaryAdmin.cshtml (75%) create mode 100644 src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml diff --git a/src/Orchard.Web/Core/Containers/Drivers/ContainerPartDriver.cs b/src/Orchard.Web/Core/Containers/Drivers/ContainerPartDriver.cs index 11bf406ee..081c5ffd7 100644 --- a/src/Orchard.Web/Core/Containers/Drivers/ContainerPartDriver.cs +++ b/src/Orchard.Web/Core/Containers/Drivers/ContainerPartDriver.cs @@ -1,12 +1,16 @@ -using System.Linq; +using System; +using System.Linq; +using System.Web.Mvc; using System.Web.Routing; using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Handlers; using Orchard.ContentManagement.MetaData; using Orchard.Core.Common.Models; using Orchard.Core.Containers.Models; using Orchard.Core.Containers.Settings; +using Orchard.Core.Containers.ViewModels; using Orchard.Data; using Orchard.Localization; using Orchard.UI.Notify; @@ -42,17 +46,31 @@ namespace Orchard.Core.Containers.Drivers { Services.Notifier.Warning(T("There are no content types in the system with a Containable part attached. Consider adding a Containable part to some content type, existing or new, in order to relate items to this (Container enabled) item.")); } - return Editor(part, null, shapeHelper); + return Editor(part, (IUpdateModel)null, shapeHelper); } protected override DriverResult Editor(ContainerPart part, IUpdateModel updater, dynamic shapeHelper) { return ContentShape( "Parts_Container_Edit", () => { - if (updater != null) - updater.TryUpdateModel(part, "Container", null, null); + var model = new ContainerViewModel { Part = part }; + // todo: is there a non-string comparison way to find ConaintableParts? + var containables = _contentDefinitionManager.ListTypeDefinitions().Where(td => td.Parts.Any(p => p.PartDefinition.Name == "ContainablePart")).ToList(); + var listItems = new[] { new SelectListItem { Text = T("(Any)").Text, Value = "" } } + .Concat(containables.Select(x => new SelectListItem { + Value = Convert.ToString(x.Name), + Text = x.DisplayName, + Selected = x.Name == model.Part.Record.ItemContentType, + })) + .ToList(); - return shapeHelper.EditorTemplate(TemplateName: "Container", Model: part, Prefix: "Container"); + model.AvailableContainables = new SelectList(listItems, "Value", "Text", model.Part.Record.ItemContentType); + + if (updater != null) { + updater.TryUpdateModel(model, "Container", null, null); + } + + return shapeHelper.EditorTemplate(TemplateName: "Container", Model: model, Prefix: "Container"); }); } } @@ -71,20 +89,5 @@ namespace Orchard.Core.Containers.Drivers { part.Record.OrderByDirection = (int)OrderByDirection.Descending; }); } - - protected override void GetItemMetadata(GetContentItemMetadataContext context) { - var container = context.ContentItem.As(); - - if (container == null) - return; - - // containers link to their contents in admin screens - context.Metadata.AdminRouteValues = new RouteValueDictionary { - {"Area", "Contents"}, - {"Controller", "Admin"}, - {"Action", "List"}, - {"containerId", container.Id} - }; - } } } diff --git a/src/Orchard.Web/Core/Containers/Migrations.cs b/src/Orchard.Web/Core/Containers/Migrations.cs index 4a91eaec6..bab60d441 100644 --- a/src/Orchard.Web/Core/Containers/Migrations.cs +++ b/src/Orchard.Web/Core/Containers/Migrations.cs @@ -45,5 +45,10 @@ namespace Orchard.Core.Containers { return 1; } + + public int UpdateFrom1() { + SchemaBuilder.AlterTable("ContainerPartRecord", table => table.AddColumn("ItemContentType")); + return 2; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Containers/Models/ContainerPart.cs b/src/Orchard.Web/Core/Containers/Models/ContainerPart.cs index 31615d26a..6ee085097 100644 --- a/src/Orchard.Web/Core/Containers/Models/ContainerPart.cs +++ b/src/Orchard.Web/Core/Containers/Models/ContainerPart.cs @@ -6,6 +6,7 @@ namespace Orchard.Core.Containers.Models { } public class ContainerPartRecord : ContentPartRecord { + public virtual string ItemContentType { get; set; } public virtual bool Paginated { get; set; } public virtual int PageSize { get; set; } public virtual string OrderByProperty { get; set; } diff --git a/src/Orchard.Web/Core/Containers/Placement.info b/src/Orchard.Web/Core/Containers/Placement.info index 17d6f76a9..9feba91ba 100644 --- a/src/Orchard.Web/Core/Containers/Placement.info +++ b/src/Orchard.Web/Core/Containers/Placement.info @@ -3,7 +3,6 @@ @@ -11,7 +10,4 @@ - - - diff --git a/src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs b/src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs new file mode 100644 index 000000000..a5dcb7a6f --- /dev/null +++ b/src/Orchard.Web/Core/Containers/ViewModels/ContainerViewModel.cs @@ -0,0 +1,9 @@ +using System.Web.Mvc; +using Orchard.Core.Containers.Models; + +namespace Orchard.Core.Containers.ViewModels { + public class ContainerViewModel { + public ContainerPart Part { get; set; } + public SelectList AvailableContainables { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Containers/Views/EditorTemplates/Container.cshtml b/src/Orchard.Web/Core/Containers/Views/EditorTemplates/Container.cshtml index d9cc0c7d2..b799df38d 100644 --- a/src/Orchard.Web/Core/Containers/Views/EditorTemplates/Container.cshtml +++ b/src/Orchard.Web/Core/Containers/Views/EditorTemplates/Container.cshtml @@ -1,27 +1,31 @@ -@model Orchard.Core.Containers.Models.ContainerPart +@model Orchard.Core.Containers.ViewModels.ContainerViewModel @using Orchard.Core.Containers.Models;
- @Html.LabelFor(m => m.Record.OrderByProperty, T("Order by")) - + @Html.SelectOption(Model.Part.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text) + @Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Title", T("Title").Text) + @Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text) + @Html.SelectOption(Model.Part.Record.OrderByProperty, "CustomPropertiesPart.CustomOne", T("Custom 1").Text) + @Html.SelectOption(Model.Part.Record.OrderByProperty, "CustomPropertiesPart.CustomTwo", T("Custom 2").Text) + @Html.SelectOption(Model.Part.Record.OrderByProperty, "CustomPropertiesPart.CustomThree", T("Custom 3").Text) - + @Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text) + @Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
- @Html.LabelFor(m => m.Record.PageSize, T("Page size")) - @Html.TextBoxFor(m => m.Record.PageSize, new { @class = "text text-small" }) + @Html.LabelFor(m => m.Part.Record.PageSize, T("Page size")) + @Html.TextBoxFor(m => m.Part.Record.PageSize, new { @class = "text text-small" }) - @Html.CheckBoxFor(m => m.Record.Paginated) - + @Html.CheckBoxFor(m => m.Part.Record.Paginated) +
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index 79e7fb403..94384eb18 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -9,6 +9,7 @@ using Orchard.ContentManagement.Aspects; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Models; using Orchard.Core.Common.Models; +using Orchard.Core.Containers.Models; using Orchard.Core.Contents.Settings; using Orchard.Core.Contents.ViewModels; using Orchard.Data; @@ -52,10 +53,8 @@ namespace Orchard.Core.Contents.Controllers { public ActionResult List(ListContentsViewModel model, PagerParameters pagerParameters) { Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); - if (model.ContainerId != null && _contentManager.GetLatest((int)model.ContainerId) == null) - return HttpNotFound(); - var query = _contentManager.Query(VersionOptions.Latest, GetCreatableTypes().Select(ctd => ctd.Name).ToArray()); + var query = _contentManager.Query(VersionOptions.Latest, GetCreatableTypes(false).Select(ctd => ctd.Name).ToArray()); if (!string.IsNullOrEmpty(model.TypeName)) { var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(model.TypeName); @@ -68,10 +67,6 @@ namespace Orchard.Core.Contents.Controllers { query = query.ForType(model.TypeName); } - if (model.ContainerId != null) { - query = query.Join().Where(cr => cr.Container.Id == model.ContainerId); - } - switch (model.Options.OrderBy) { case ContentsOrder.Modified: //query = query.OrderByDescending(ci => ci.ContentItemRecord.Versions.Single(civr => civr.Latest).Id); @@ -87,7 +82,7 @@ namespace Orchard.Core.Contents.Controllers { } model.Options.SelectedFilter = model.TypeName; - model.Options.FilterOptions = GetCreatableTypes() + model.Options.FilterOptions = GetCreatableTypes(false) .Select(ctd => new KeyValuePair(ctd.Name, ctd.DisplayName)) .ToList().OrderBy(kvp => kvp.Key); @@ -107,8 +102,8 @@ namespace Orchard.Core.Contents.Controllers { return View((object)viewModel); } - private IEnumerable GetCreatableTypes() { - return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => ctd.Settings.GetModel().Creatable); + private IEnumerable GetCreatableTypes(bool andContainable) { + return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => ctd.Settings.GetModel().Creatable && (!andContainable || ctd.Parts.Any(p => p.PartDefinition.Name == "ContainablePart")) ); } [HttpPost, ActionName("List")] @@ -117,7 +112,7 @@ namespace Orchard.Core.Contents.Controllers { var routeValues = ControllerContext.RouteData.Values; if (options != null) { routeValues["Options.OrderBy"] = options.OrderBy; //todo: don't hard-code the key - if (GetCreatableTypes().Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) { + if (GetCreatableTypes(false).Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) { routeValues["id"] = options.SelectedFilter; } else { @@ -177,22 +172,29 @@ namespace Orchard.Core.Contents.Controllers { return this.RedirectLocal(returnUrl, () => RedirectToAction("List")); } - ActionResult CreatableTypeList() { - dynamic viewModel = Shape.ViewModel(ContentTypes: GetCreatableTypes()); + ActionResult CreatableTypeList(int? containerId) { + dynamic viewModel = Shape.ViewModel(ContentTypes: GetCreatableTypes(containerId.HasValue), ContainerId: containerId); // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation. return View("CreatableTypeList", (object)viewModel); } - public ActionResult Create(string id) { + public ActionResult Create(string id, int? containerId) { if (string.IsNullOrEmpty(id)) - return CreatableTypeList(); + return CreatableTypeList(containerId); var contentItem = _contentManager.New(id); if (!Services.Authorizer.Authorize(Permissions.PublishContent, contentItem, T("Cannot create content"))) return new HttpUnauthorizedResult(); + if (containerId.HasValue && contentItem.Is()) { + var common = contentItem.As(); + if (common != null) { + common.Container = _contentManager.Get(containerId.Value); + } + } + dynamic model = _contentManager.BuildEditor(contentItem); // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation. return View((object)model); diff --git a/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs b/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs index bf6cd6be5..c3171687b 100644 --- a/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs +++ b/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs @@ -8,7 +8,6 @@ namespace Orchard.Core.Contents.ViewModels { } public string Id { get; set; } - public int? ContainerId { get; set; } public string TypeName { get { return Id; } diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.cshtml b/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.cshtml index c5c5d445c..277567394 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.cshtml +++ b/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.cshtml @@ -1,5 +1,5 @@ @{ Layout.Title = T("Create New Content").ToString(); } @foreach (var type in Model.ContentTypes) { -

@Html.ActionLink((string)type.DisplayName, "Create", new { Area = "Contents", Id = (string)type.Name })

+

@Html.ActionLink((string)type.DisplayName, "Create", new { Area = "Contents", Id = (string)type.Name, ContainerId = Model.ContainerId })

} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index 2109b0297..54d6e3a87 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -87,6 +87,7 @@ + @@ -99,7 +100,6 @@ - @@ -383,9 +383,6 @@ - - - diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs new file mode 100644 index 000000000..5fbc671d4 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/Controllers/AdminController.cs @@ -0,0 +1,269 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Collections.Generic; +using System.Web.Mvc; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.Core.Common.Models; +using Orchard.Core.Containers.Models; +using Orchard.Core.Contents; +using Orchard.Core.Contents.Controllers; +using Orchard.Core.Contents.Settings; +using Orchard.Data; +using Orchard.DisplayManagement; +using Orchard.DisplayManagement.Shapes; +using Orchard.Lists.ViewModels; +using Orchard.Localization; +using Orchard; +using Orchard.Logging; +using Orchard.Mvc.Extensions; +using Orchard.Settings; +using Orchard.UI.Navigation; +using Orchard.UI.Notify; + +namespace Lists.Controllers { + public class AdminController : Controller { + private readonly IContentManager _contentManager; + private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly ITransactionManager _transactionManager; + private readonly ISiteService _siteService; + + public IOrchardServices Services { get; set; } + + public AdminController( + IOrchardServices orchardServices, + IContentManager contentManager, + IContentDefinitionManager contentDefinitionManager, + ITransactionManager transactionManager, + ISiteService siteService, + IShapeFactory shapeFactory) { + Services = orchardServices; + _contentManager = contentManager; + _contentDefinitionManager = contentDefinitionManager; + _transactionManager = transactionManager; + _siteService = siteService; + T = NullLocalizer.Instance; + Logger = NullLogger.Instance; + Shape = shapeFactory; + } + + public Localizer T { get; set; } + public ILogger Logger { get; set; } + dynamic Shape { get; set; } + + private IEnumerable GetContainableTypes() { + return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => ctd.Parts.Any(c => c.PartDefinition.Name == "ContainablePart") && ctd.Settings.GetModel().Creatable); + } + + public ActionResult List(ListContentsViewModel model, PagerParameters pagerParameters) { + var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); + var container = _contentManager.GetLatest((int)model.ContainerId); + if (container == null) { + return HttpNotFound(); + } + var restrictedContentType = container.As().Record.ItemContentType; + var hasRestriction = !string.IsNullOrEmpty(restrictedContentType); + + var metadata = container.ContentManager.GetItemMetadata(container); + model.ContainerDisplayName = metadata.DisplayText; + if (string.IsNullOrEmpty(model.ContainerDisplayName)) { + model.ContainerDisplayName = container.ContentType; + } + + var query = _contentManager.Query(VersionOptions.Latest); + + if (hasRestriction) { + model.FilterByContentType = restrictedContentType; + } + + if (!string.IsNullOrEmpty(model.FilterByContentType)) { + var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(model.FilterByContentType); + if (contentTypeDefinition == null) + return HttpNotFound(); + query = query.ForType(model.FilterByContentType); + } + query = query.Join().Where(cr => cr.Container.Id == model.ContainerId); + + switch (model.Options.OrderBy) { + case ContentsOrder.Modified: + query = query.OrderByDescending(cr => cr.ModifiedUtc); + break; + case ContentsOrder.Published: + query = query.OrderByDescending(cr => cr.PublishedUtc); + break; + case ContentsOrder.Created: + query = query.OrderByDescending(cr => cr.CreatedUtc); + break; + } + + model.Options.SelectedFilter = model.FilterByContentType; + + if (!hasRestriction) { + model.Options.FilterOptions = GetContainableTypes() + .Select(ctd => new KeyValuePair(ctd.Name, ctd.DisplayName)) + .ToList().OrderBy(kvp => kvp.Key); + } + + var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count()); + var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList(); + + var list = Shape.List(); + list.AddRange(pageOfContentItems.Select(ci => _contentManager.BuildDisplay(ci, "SummaryAdmin"))); + + dynamic viewModel = Shape.ViewModel() + .ContentItems(list) + .Pager(pagerShape) + .ContainerId(model.ContainerId) + .Options(model.Options) + .HasRestriction(hasRestriction) + .ContainerDisplayName(model.ContainerDisplayName) + .ContainerContentType(container.ContentType) + .ContainerItemContentType(hasRestriction ? restrictedContentType : (model.FilterByContentType ?? "")) + .OtherLists(_contentManager.Query(VersionOptions.Latest).List() + .Select(part => part.ContentItem) + .Where(item => item != container) + .OrderBy(item => item.As().VersionPublishedUtc)); + + // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation. + return View((object)viewModel); + } + + [HttpPost, ActionName("List")] + [FormValueRequired("submit.BulkEdit")] + public ActionResult ListPOST(ContentOptions options, IEnumerable itemIds, int? targetContainerId, string returnUrl) { + if (itemIds != null) { + switch (options.BulkAction) { + case ContentsBulkAction.None: + break; + case ContentsBulkAction.PublishNow: + if (!BulkPublishNow(itemIds)) { + return new HttpUnauthorizedResult(); + } + break; + case ContentsBulkAction.Unpublish: + if (!BulkUnpublish(itemIds)) { + return new HttpUnauthorizedResult(); + } + break; + case ContentsBulkAction.Remove: + if (!BulkRemove(itemIds)) { + return new HttpUnauthorizedResult(); + } + break; + case ContentsBulkAction.RemoveFromList: + if (!BulkRemoveFromList(itemIds)) { + return new HttpUnauthorizedResult(); + } + break; + case ContentsBulkAction.MoveToList: + if (!BulkMoveToList(itemIds, targetContainerId)) { + return new HttpUnauthorizedResult(); + } + break; + + default: + throw new ArgumentOutOfRangeException(); + } + } + + return this.RedirectLocal(returnUrl, () => RedirectToAction("List")); + } + + private bool BulkMoveToList(IEnumerable itemIds, int? targetContainerId) { + if (!targetContainerId.HasValue) { + Services.Notifier.Information(T("Please select the list to move the items to.")); + return true; + } + var id = targetContainerId.Value; + var targetContainer = _contentManager.Get(id); + if (targetContainer == null) { + Services.Notifier.Information(T("Please select the list to move the items to.")); + return true; + } + var itemContentType = targetContainer.Record.ItemContentType; + + foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) { + if (!Services.Authorizer.Authorize(Permissions.EditContent, item, T("Couldn't move selected content."))) { + return false; + } + // ensure the item can be in that container. + if (!string.IsNullOrEmpty(itemContentType) && item.ContentType != itemContentType) { + Services.Notifier.Information(T("One or more items could not be moved to the '{0}' list because it is restricted to containing items of type '{1}'.", _contentManager.GetItemMetadata(item).DisplayText, itemContentType)); + return true; // todo: transactions + } + + item.As().Record.Container = targetContainer.ContentItem.Record; + } + Services.Notifier.Information(T("Content successfully moved to {1}.", + Url.Action("List", new { containerId = targetContainerId }), _contentManager.GetItemMetadata(targetContainer).DisplayText)); + return true; + } + + private bool BulkRemoveFromList(IEnumerable itemIds) { + foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) { + if (!Services.Authorizer.Authorize(Permissions.EditContent, item, T("Couldn't remove selected content from the list."))) { + return false; + } + item.As().Record.Container = null; + } + Services.Notifier.Information(T("Content successfully removed from the list.")); + return true; + } + + private bool BulkRemove(IEnumerable itemIds) { + foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) { + if (!Services.Authorizer.Authorize(Permissions.DeleteContent, item, T("Couldn't remove selected content."))) { + return false; + } + + _contentManager.Remove(item); + } + Services.Notifier.Information(T("Content successfully removed.")); + return true; + } + + private bool BulkUnpublish(IEnumerable itemIds) { + foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) { + if (!Services.Authorizer.Authorize(Permissions.PublishContent, item, T("Couldn't unpublish selected content."))) { + return false; + } + + _contentManager.Unpublish(item); + } + Services.Notifier.Information(T("Content successfully unpublished.")); + return true; + } + + private bool BulkPublishNow(IEnumerable itemIds) { + foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) { + if (!Services.Authorizer.Authorize(Permissions.PublishContent, item, T("Couldn't publish selected content."))) + return false; + + _contentManager.Publish(item); + } + Services.Notifier.Information(T("Content successfully published.")); + return true; + } + + [HttpPost, ActionName("List")] + [FormValueRequired("submit.Filter")] + public ActionResult ListFilterPOST(ContentOptions options) { + var routeValues = ControllerContext.RouteData.Values; + if (options != null) { + routeValues["Options.OrderBy"] = options.OrderBy; + if (GetContainableTypes().Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) { + routeValues["filterByContentType"] = options.SelectedFilter; + } + else { + routeValues.Remove("filterByContentType"); + } + } + + return RedirectToAction("List", routeValues); + } + + + } +} diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Handlers/ContainerPartHandler.cs b/src/Orchard.Web/Modules/Orchard.Lists/Handlers/ContainerPartHandler.cs new file mode 100644 index 000000000..6abc4c5e1 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/Handlers/ContainerPartHandler.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Web.Routing; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; +using Orchard.Core.Containers.Models; +using Orchard.Data; + +namespace Orchard.Lists.Handlers { + public class ContainerPartHandler : ContentHandler { + public ContainerPartHandler() { + } + + protected override void GetItemMetadata(GetContentItemMetadataContext context) { + var container = context.ContentItem.As(); + + if (container == null) + return; + + // containers link to their contents in admin screens + context.Metadata.AdminRouteValues = new RouteValueDictionary { + {"Area", "Orchard.Lists"}, + {"Controller", "Admin"}, + {"Action", "List"}, + {"containerId", container.Id} + }; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Orchard.Lists.csproj b/src/Orchard.Web/Modules/Orchard.Lists/Orchard.Lists.csproj index ed0881b70..cae96d59b 100644 --- a/src/Orchard.Web/Modules/Orchard.Lists/Orchard.Lists.csproj +++ b/src/Orchard.Web/Modules/Orchard.Lists/Orchard.Lists.csproj @@ -39,6 +39,7 @@ AllRules.ruleset + False ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll @@ -47,7 +48,11 @@ + + + + @@ -61,6 +66,7 @@ + @@ -76,7 +82,21 @@ - + + + + + + + + + + + + + + Designer + diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Placement.info b/src/Orchard.Web/Modules/Orchard.Lists/Placement.info new file mode 100644 index 000000000..95aaa5357 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/Placement.info @@ -0,0 +1,9 @@ + + + + + + + diff --git a/src/Orchard.Web/Core/Contents/Routes.cs b/src/Orchard.Web/Modules/Orchard.Lists/Routes.cs similarity index 76% rename from src/Orchard.Web/Core/Contents/Routes.cs rename to src/Orchard.Web/Modules/Orchard.Lists/Routes.cs index 8ceac5787..dcb67529e 100644 --- a/src/Orchard.Web/Core/Contents/Routes.cs +++ b/src/Orchard.Web/Modules/Orchard.Lists/Routes.cs @@ -3,7 +3,7 @@ using System.Web.Mvc; using System.Web.Routing; using Orchard.Mvc.Routes; -namespace Orchard.Core.Contents { +namespace Orchard.Lists { public class Routes : IRouteProvider { public void GetRoutes(ICollection routes) { foreach (RouteDescriptor routeDescriptor in GetRoutes()) { @@ -16,36 +16,36 @@ namespace Orchard.Core.Contents { new RouteDescriptor { Priority = 5, Route = new Route( - "Admin/Contents/List/{id}/InContainer/{containerId}", + "Admin/Orchard.Lists/{containerId}/{filterByContentType}", new RouteValueDictionary { {"area", "Contents"}, {"controller", "Admin"}, - {"action", "List"} + {"action", "List"}, + {"filterByContentType", ""} }, - new RouteValueDictionary { - {"id", @"\w+"}, + new RouteValueDictionary{ + {"filterByContentType", @"\w+"}, {"containerId", @"\d+"} }, new RouteValueDictionary { - {"area", "Contents"} + {"area", "Orchard.Lists"} }, new MvcRouteHandler()) }, new RouteDescriptor { Priority = 5, Route = new Route( - "Admin/Contents/List/InContainer/{containerId}", + "Admin/Orchard.Lists/{containerId}", new RouteValueDictionary { - {"area", "Contents"}, + {"area", "Orchard.Lists"}, {"controller", "Admin"}, - {"action", "List"}, - {"id", ""} + {"action", "List"} }, - new RouteValueDictionary{ + new RouteValueDictionary { {"containerId", @"\d+"} }, new RouteValueDictionary { - {"area", "Contents"} + {"area", "Orchard.Lists"} }, new MvcRouteHandler()) } diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Scripts/Web.config b/src/Orchard.Web/Modules/Orchard.Lists/Scripts/Web.config new file mode 100644 index 000000000..0dc62ece6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/Scripts/Web.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Scripts/orchard-lists-admin.js b/src/Orchard.Web/Modules/Orchard.Lists/Scripts/orchard-lists-admin.js new file mode 100644 index 000000000..96efbf3d3 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/Scripts/orchard-lists-admin.js @@ -0,0 +1,10 @@ +jQuery("#publishActions").bind("change", function () { + var value = jQuery(this).val(), + target = jQuery("#TargetContainerId"); + if (value === "MoveToList") { + target.css("display", "inline"); + } + else { + target.css("display", "none"); + } +}); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Lists/ViewModels/ListContentsViewModel.cs b/src/Orchard.Web/Modules/Orchard.Lists/ViewModels/ListContentsViewModel.cs new file mode 100644 index 000000000..822ffcf08 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/ViewModels/ListContentsViewModel.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using Orchard.ContentManagement; + +namespace Orchard.Lists.ViewModels { + public class ListContentsViewModel { + public ListContentsViewModel() { + Options = new ContentOptions(); + } + + public string FilterByContentType { get; set; } + public int? ContainerId { get; set; } + public string ContainerDisplayName { get; set; } + + public int? Page { get; set; } + public IList Entries { get; set; } + public ContentOptions Options { get; set; } + + #region Nested type: Entry + + public class Entry { + public ContentItem ContentItem { get; set; } + public ContentItemMetadata ContentItemMetadata { get; set; } + } + + #endregion + } + + public class ContentOptions { + public ContentOptions() { + OrderBy = ContentsOrder.Modified; + BulkAction = ContentsBulkAction.None; + } + public string SelectedFilter { get; set; } + public IEnumerable> FilterOptions { get; set; } + public ContentsOrder OrderBy { get; set; } + public ContentsBulkAction BulkAction { get; set; } + } + + public enum ContentsOrder { + Modified, + Published, + Created + } + + public enum ContentsBulkAction { + None, + PublishNow, + Unpublish, + Remove, + RemoveFromList, + MoveToList + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Views/Admin/List.cshtml b/src/Orchard.Web/Modules/Orchard.Lists/Views/Admin/List.cshtml new file mode 100644 index 000000000..ad8723dbb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/Views/Admin/List.cshtml @@ -0,0 +1,64 @@ +@using Orchard.Lists.ViewModels; +@{ + Script.Include("orchard-lists-admin.js"); + + string createLinkText = string.IsNullOrEmpty(Model.ContainerItemContentType) ? T("Create New Content").ToString() : T("Create New {0}", Model.ContainerItemContentType).ToString(); + + Layout.Title = T("Manage Content for {0}", Model.ContainerDisplayName); + + var lists = ((IEnumerable)Model.OtherLists).Select( + contentItem => new SelectListItem { + Text = contentItem.ContentType + ": " + contentItem.ContentManager.GetItemMetadata(contentItem).DisplayText, + Value = contentItem.Id.ToString(System.Globalization.CultureInfo.InvariantCulture) + }).ToList(); + lists.Insert(0, new SelectListItem { Text = T("Move to...").ToString(), Value = "" }); +} + + +
 
+@Display.Parts_Container_Manage(ContainerDisplayName: Model.ContainerDisplayName, ContainerContentType: Model.ContainerContentType, ContainerId: Model.ContainerId) + +
+ @Html.ActionLink(createLinkText, "Create", new { Area = "Contents", Id = (string)Model.Options.SelectedFilter, ContainerId = Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }, new { @class = "button primaryAction" }) +
+@using (Html.BeginFormAntiForgeryPost()) { +
+ + + @Html.DropDownList("TargetContainerId", lists, new { id = "TargetContainerId" }) + +
+
+ @if(!Model.HasRestriction) { + + + } + + + +
+
+@Display(Model.ContentItems) +
+@Display(Model.Pager) +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Containers/Views/Parts.Container.Contained.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Contained.SummaryAdmin.cshtml similarity index 75% rename from src/Orchard.Web/Core/Containers/Views/Parts.Container.Contained.SummaryAdmin.cshtml rename to src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Contained.SummaryAdmin.cshtml index 1a1a0534a..48d8e4653 100644 --- a/src/Orchard.Web/Core/Containers/Views/Parts.Container.Contained.SummaryAdmin.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Contained.SummaryAdmin.cshtml @@ -5,5 +5,5 @@ ContentPart contentPart = Model.ContentPart; } @if (contentPart.Is()) { - @Html.Link(T("Contained Items").Text, Url.Action("List", "Admin", new { area = "Contents", containerId = contentPart.Id }))@T(" | ") + @Html.Link(T("Contained Items").Text, Url.Action("List", "Admin", new { area = "Orchard.Lists", containerId = contentPart.Id }))@T(" | ") } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml new file mode 100644 index 000000000..b57c18609 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Lists/Views/Parts.Container.Manage.cshtml @@ -0,0 +1,8 @@ +
+

+ @Html.ActionLink(T("Show Other Lists").ToString(), "List", new { Area = "Contents", Id = Model.ContainerContentType }) | + @Html.ActionLink(T("Show Orphaned Content Items").ToString(), "Orphaned") | + @Html.ActionLink(T("{0} Properties", (string)Model.ContainerContentType).ToString(), "Edit", new { Area = "Contents", Id = Model.ContainerId }) + +

+
\ No newline at end of file