diff --git a/ClickToRunAzureInDevFabric.cmd b/ClickToRunAzureInDevFabric.cmd new file mode 100644 index 000000000..3e1ba1773 --- /dev/null +++ b/ClickToRunAzureInDevFabric.cmd @@ -0,0 +1,5 @@ +SET CDIR = %CD% +call "%ProgramFiles%\Windows Azure SDK\v1.3\bin\setenv.cmd" +csrun /devstore +csrun /run:"%CDIR %\build\Compile\Orchard.Azure.CloudService.csx";"%CDIR %\src\Orchard.Azure\Orchard.Azure.CloudService\ServiceConfiguration.cscfg" /launchbrowser +pause \ No newline at end of file diff --git a/src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs b/src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs index 5c5e33d98..524c02777 100644 --- a/src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs +++ b/src/Orchard.Azure/Environment/Configuration/AzureShellSettingsManager.cs @@ -83,32 +83,27 @@ namespace Orchard.Azure.Environment.Configuration { } } - class Content { - public string Name { get; set; } - public string DataProvider { get; set; } - public string DataConnectionString { get; set; } - public string DataPrefix { get; set; } - public string RequestUrlHost { get; set; } - public string RequestUrlPrefix { get; set; } - public string State { get; set; } - } - - static ShellSettings ParseSettings(string text) { + static ShellSettings ParseSettings(string text) + { var shellSettings = new ShellSettings(); - if ( String.IsNullOrEmpty(text) ) + if (String.IsNullOrEmpty(text)) return shellSettings; string[] settings = text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); - foreach ( var setting in settings ) { + foreach (var setting in settings) + { string[] settingFields = setting.Split(new[] { ":" }, StringSplitOptions.RemoveEmptyEntries); int fieldsLength = settingFields.Length; - if ( fieldsLength != 2 ) + if (fieldsLength != 2) continue; - for ( int i = 0; i < fieldsLength; i++ ) { + for (int i = 0; i < fieldsLength; i++) + { settingFields[i] = settingFields[i].Trim(); } - if ( settingFields[1] != "null" ) { - switch ( settingFields[0] ) { + if (settingFields[1] != "null") + { + switch (settingFields[0]) + { case "Name": shellSettings.Name = settingFields[1]; break; @@ -130,24 +125,38 @@ namespace Orchard.Azure.Environment.Configuration { case "RequestUrlPrefix": shellSettings.RequestUrlPrefix = settingFields[1]; break; + case "EncryptionAlgorithm": + shellSettings.EncryptionAlgorithm = settingFields[1]; + break; + case "EncryptionKey": + shellSettings.EncryptionKey = settingFields[1]; + break; + case "EncryptionIV": + shellSettings.EncryptionIV = settingFields[1]; + break; } } } return shellSettings; } - static string ComposeSettings(ShellSettings settings) { - if ( settings == null ) + static string ComposeSettings(ShellSettings settings) + { + if (settings == null) return ""; - return string.Format("Name: {0}\r\nDataProvider: {1}\r\nDataConnectionString: {2}\r\nDataPrefix: {3}\r\nRequestUrlHost: {4}\r\nRequestUrlPrefix: {5}\r\nState: {6}\r\n", + return string.Format("Name: {0}\r\nDataProvider: {1}\r\nDataConnectionString: {2}\r\nDataPrefix: {3}\r\nRequestUrlHost: {4}\r\nRequestUrlPrefix: {5}\r\nState: {6}\r\nEncryptionAlgorithm: {7}\r\nEncryptionKey: {8}\r\nEncryptionIV: {9}\r\n", settings.Name, settings.DataProvider, settings.DataConnectionString ?? "null", settings.DataTablePrefix ?? "null", settings.RequestUrlHost ?? "null", settings.RequestUrlPrefix ?? "null", - settings.State != null ? settings.State.ToString() : String.Empty); + settings.State != null ? settings.State.ToString() : String.Empty, + settings.EncryptionAlgorithm ?? "null", + settings.EncryptionKey ?? "null", + settings.EncryptionIV ?? "null" + ); } } } diff --git a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef index fb41cf303..462e8f2ae 100644 --- a/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef +++ b/src/Orchard.Azure/Orchard.Azure.CloudService/ServiceDefinition.csdef @@ -1,13 +1,6 @@  - - - - - - - diff --git a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj index 981db132f..4db91e723 100644 --- a/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj +++ b/src/Orchard.Azure/Orchard.Azure.Web/Orchard.Azure.Web.csproj @@ -75,8 +75,9 @@ False - - True + + False + ..\..\..\lib\sqlce\System.Data.SqlServerCe.dll False diff --git a/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs b/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs index ee299df51..80fde47de 100644 --- a/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs +++ b/src/Orchard.Tests/Stubs/StubWorkContextAccessor.cs @@ -60,6 +60,11 @@ namespace Orchard.Tests.Stubs { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } + + public int PageSize { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } } public class StubUser : IUser { diff --git a/src/Orchard.Web/Core/Containers/Controllers/ItemController.cs b/src/Orchard.Web/Core/Containers/Controllers/ItemController.cs index db89f21be..6bb1e3618 100644 --- a/src/Orchard.Web/Core/Containers/Controllers/ItemController.cs +++ b/src/Orchard.Web/Core/Containers/Controllers/ItemController.cs @@ -11,20 +11,29 @@ using Orchard.Themes; using Orchard.UI.Navigation; namespace Orchard.Core.Containers.Controllers { + using Orchard.Settings; + public class ItemController : Controller { private readonly IContentManager _contentManager; private readonly IContainersPathConstraint _containersPathConstraint; + private readonly ISiteService _siteService; + + public ItemController( + IContentManager contentManager, + IContainersPathConstraint containersPathConstraint, + IShapeFactory shapeFactory, + ISiteService siteService) { - public ItemController(IContentManager contentManager, IContainersPathConstraint containersPathConstraint, IShapeFactory shapeFactory) { _contentManager = contentManager; _containersPathConstraint = containersPathConstraint; + _siteService = siteService; Shape = shapeFactory; } dynamic Shape { get; set; } [Themed] - public ActionResult Display(string path, Pager pager) { + public ActionResult Display(string path, PagerParameters pagerParameters) { var matchedPath = _containersPathConstraint.FindPath(path); if (string.IsNullOrEmpty(matchedPath)) { throw new ApplicationException("404 - should not have passed path constraint"); @@ -51,7 +60,8 @@ namespace Orchard.Core.Containers.Controllers { var descendingOrder = container.As().Record.OrderByDirection == (int) OrderByDirection.Descending; query = query.OrderBy(container.As().Record.OrderByProperty, descendingOrder); - pager.PageSize = pager.PageSize != Pager.PageSizeDefault && container.As().Record.Paginated + Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); + pager.PageSize = pagerParameters.PageSize != null && container.As().Record.Paginated ? pager.PageSize : container.As().Record.PageSize; var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count()); diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index c638153f0..f8a16d634 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -17,6 +17,7 @@ using Orchard.Localization; using Orchard.Logging; using Orchard.UI.Navigation; using Orchard.UI.Notify; +using Orchard.Settings; namespace Orchard.Core.Contents.Controllers { [ValidateInput(false)] @@ -24,17 +25,20 @@ namespace Orchard.Core.Contents.Controllers { private readonly IContentManager _contentManager; private readonly IContentDefinitionManager _contentDefinitionManager; private readonly ITransactionManager _transactionManager; + private readonly ISiteService _siteService; 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; @@ -45,7 +49,8 @@ namespace Orchard.Core.Contents.Controllers { public Localizer T { get; set; } public ILogger Logger { get; set; } - public ActionResult List(ListContentsViewModel model, Pager pager) { + 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(); diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index c06905952..0c9308d99 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -104,6 +104,7 @@ + diff --git a/src/Orchard.Web/Core/Routable/Events/ISlugEventHandler.cs b/src/Orchard.Web/Core/Routable/Events/ISlugEventHandler.cs new file mode 100644 index 000000000..a178aed71 --- /dev/null +++ b/src/Orchard.Web/Core/Routable/Events/ISlugEventHandler.cs @@ -0,0 +1,17 @@ +using Orchard.Events; + +namespace Orchard.Core.Routable.Events { + public interface ISlugEventHandler : IEventHandler { + void FillingSlugFromTitle(FillSlugContext context); + void FilledSlugFromTitle(FillSlugContext context); + } + + public class FillSlugContext { + public FillSlugContext(string slug) { + Slug = slug; + } + + public string Slug { get; set; } + public bool Adjusted { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs index 2ddea2f21..889720db9 100644 --- a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs +++ b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs @@ -1,18 +1,23 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; +using System.Text; using System.Text.RegularExpressions; using Orchard.ContentManagement; using Orchard.ContentManagement.Aspects; using Orchard.Core.Common.Models; +using Orchard.Core.Routable.Events; using Orchard.Core.Routable.Models; namespace Orchard.Core.Routable.Services { public class RoutableService : IRoutableService { private readonly IContentManager _contentManager; + private readonly IEnumerable _slugEventHandlers; - public RoutableService(IContentManager contentManager) { + public RoutableService(IContentManager contentManager, IEnumerable slugEventHandlers) { _contentManager = contentManager; + _slugEventHandlers = slugEventHandlers; } public void FixContainedPaths(IRoutableAspect part) { @@ -27,23 +32,47 @@ namespace Orchard.Core.Routable.Services { } } + public static string RemoveDiacritics(string slug) { + string stFormD = slug.Normalize(NormalizationForm.FormD); + StringBuilder sb = new StringBuilder(); + + for (int ich = 0; ich < stFormD.Length; ich++) { + UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]); + if (uc != UnicodeCategory.NonSpacingMark) { + sb.Append(stFormD[ich]); + } + } + + return (sb.ToString().Normalize(NormalizationForm.FormC)); + } + public void FillSlugFromTitle(TModel model) where TModel : IRoutableAspect { if (!string.IsNullOrEmpty(model.Slug) || string.IsNullOrEmpty(model.Title)) return; - var slug = model.Title; - var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""\<\>]+"); + FillSlugContext slugContext = new FillSlugContext(model.Title); - slug = dissallowed.Replace(slug, "-"); - slug = slug.Trim('-'); + foreach(ISlugEventHandler slugEventHandler in _slugEventHandlers) { + slugEventHandler.FillingSlugFromTitle(slugContext); + } - if (slug.Length > 1000) - slug = slug.Substring(0, 1000); + if (!slugContext.Adjusted) { + var disallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""\<\>]+"); - // dots are not allowed at the begin and the end of routes - slug = slug.Trim('.'); + slugContext.Slug = disallowed.Replace(slugContext.Slug, "-").Trim('-'); - model.Slug = slug.ToLowerInvariant(); + if (slugContext.Slug.Length > 1000) + slugContext.Slug = slugContext.Slug.Substring(0, 1000); + + // dots are not allowed at the begin and the end of routes + slugContext.Slug = RemoveDiacritics(slugContext.Slug.Trim('.').ToLower()); + } + + foreach (ISlugEventHandler slugEventHandler in _slugEventHandlers) { + slugEventHandler.FilledSlugFromTitle(slugContext); + } + + model.Slug = slugContext.Slug; } public string GenerateUniqueSlug(IRoutableAspect part, IEnumerable existingPaths) { diff --git a/src/Orchard.Web/Core/Settings/Migrations.cs b/src/Orchard.Web/Core/Settings/Migrations.cs index 17c0b9561..57d45a144 100644 --- a/src/Orchard.Web/Core/Settings/Migrations.cs +++ b/src/Orchard.Web/Core/Settings/Migrations.cs @@ -90,6 +90,7 @@ namespace Orchard.Core.Settings { .Column("HomePage") .Column("SiteCulture") .Column("ResourceDebugMode", c => c.WithDefault("FromAppSetting")) + .Column("PageSize") ); return 1; diff --git a/src/Orchard.Web/Core/Settings/Models/SiteSettingsPart.cs b/src/Orchard.Web/Core/Settings/Models/SiteSettingsPart.cs index fa6d8fdc3..3e5094699 100644 --- a/src/Orchard.Web/Core/Settings/Models/SiteSettingsPart.cs +++ b/src/Orchard.Web/Core/Settings/Models/SiteSettingsPart.cs @@ -8,28 +8,39 @@ namespace Orchard.Core.Settings.Models { get { return Record.PageTitleSeparator; } set { Record.PageTitleSeparator = value; } } + public string SiteName { get { return Record.SiteName; } set { Record.SiteName = value; } } + public string SiteSalt { get { return Record.SiteSalt; } } + public string SuperUser { get { return Record.SuperUser; } set { Record.SuperUser = value; } } + public string HomePage { get { return Record.HomePage; } set { Record.HomePage = value; } } + public string SiteCulture { get { return Record.SiteCulture; } set { Record.SiteCulture = value; } } + public ResourceDebugMode ResourceDebugMode { get { return Record.ResourceDebugMode; } set { Record.ResourceDebugMode = value; } } + + public int PageSize { + get { return Record.PageSize; } + set { Record.PageSize = value; } + } } } diff --git a/src/Orchard.Web/Core/Settings/Models/SiteSettingsPartRecord.cs b/src/Orchard.Web/Core/Settings/Models/SiteSettingsPartRecord.cs index 2478ff91f..eb87877f5 100644 --- a/src/Orchard.Web/Core/Settings/Models/SiteSettingsPartRecord.cs +++ b/src/Orchard.Web/Core/Settings/Models/SiteSettingsPartRecord.cs @@ -3,12 +3,26 @@ using Orchard.Settings; namespace Orchard.Core.Settings.Models { public class SiteSettingsPartRecord : ContentPartRecord { + public const int DefaultPageSize = 10; + + public SiteSettingsPartRecord() { + PageSize = DefaultPageSize; + } + public virtual string SiteSalt { get; set; } + public virtual string SiteName { get; set; } + public virtual string SuperUser { get; set; } + public virtual string PageTitleSeparator { get; set; } + public virtual string HomePage { get; set; } + public virtual string SiteCulture { get; set; } + public virtual ResourceDebugMode ResourceDebugMode { get; set; } + + public virtual int PageSize { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Settings/ViewModels/SiteSettingsPartViewModel.cs b/src/Orchard.Web/Core/Settings/ViewModels/SiteSettingsPartViewModel.cs index 3c5624ff2..8bbb87d40 100644 --- a/src/Orchard.Web/Core/Settings/ViewModels/SiteSettingsPartViewModel.cs +++ b/src/Orchard.Web/Core/Settings/ViewModels/SiteSettingsPartViewModel.cs @@ -15,8 +15,7 @@ namespace Orchard.Core.Settings.ViewModels { get { return Site.ContentItem.Id; } } - public string PageTitleSeparator - { + public string PageTitleSeparator { get { return Site.Record.PageTitleSeparator; } set { Site.Record.PageTitleSeparator = value; } } @@ -40,5 +39,10 @@ namespace Orchard.Core.Settings.ViewModels { get { return Site.As().ResourceDebugMode; } set { Site.As().ResourceDebugMode = value; } } + + public int PageSize { + get { return Site.As().PageSize; } + set { Site.As().PageSize = value; } + } } } diff --git a/src/Orchard.Web/Core/Settings/Views/EditorTemplates/Parts.Settings.SiteSettingsPart.cshtml b/src/Orchard.Web/Core/Settings/Views/EditorTemplates/Parts.Settings.SiteSettingsPart.cshtml index ba9a67d96..e8d36de86 100644 --- a/src/Orchard.Web/Core/Settings/Views/EditorTemplates/Parts.Settings.SiteSettingsPart.cshtml +++ b/src/Orchard.Web/Core/Settings/Views/EditorTemplates/Parts.Settings.SiteSettingsPart.cshtml @@ -36,4 +36,9 @@ @Html.DropDownList("ResourceDebugMode", resourceDebugMode) @T("Determines whether scripts and stylesheets load in their debuggable or minified form.") +
+ + @Html.TextBoxFor(m => m.PageSize, new { @class = "textMedium" }) + @T("Determines the default number of items that are shown per page.") +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs index d54c11dc2..258b630ee 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/AdminMenu.cs @@ -25,7 +25,7 @@ namespace Orchard.Blogs { var singleBlog = blogCount == 1 ? blogs.ElementAt(0) : null; if (blogCount > 0 && singleBlog == null) { - menu.Add(T("List"), "3", + menu.Add(T("Manage Blogs"), "3", item => item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListOwnBlogs)); } else if (singleBlog != null) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs index c9a0686d1..d7ce86253 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs @@ -15,6 +15,8 @@ using Orchard.UI.Navigation; using Orchard.UI.Notify; namespace Orchard.Blogs.Controllers { + using Orchard.Settings; + [ValidateInput(false), Admin] public class BlogAdminController : Controller, IUpdateModel { private readonly IBlogService _blogService; @@ -22,6 +24,7 @@ namespace Orchard.Blogs.Controllers { private readonly IContentManager _contentManager; private readonly ITransactionManager _transactionManager; private readonly IBlogSlugConstraint _blogSlugConstraint; + private readonly ISiteService _siteService; public BlogAdminController( IOrchardServices services, @@ -30,6 +33,7 @@ namespace Orchard.Blogs.Controllers { IContentManager contentManager, ITransactionManager transactionManager, IBlogSlugConstraint blogSlugConstraint, + ISiteService siteService, IShapeFactory shapeFactory) { Services = services; _blogService = blogService; @@ -37,6 +41,7 @@ namespace Orchard.Blogs.Controllers { _contentManager = contentManager; _transactionManager = transactionManager; _blogSlugConstraint = blogSlugConstraint; + _siteService = siteService; T = NullLocalizer.Instance; Shape = shapeFactory; } @@ -147,7 +152,8 @@ namespace Orchard.Blogs.Controllers { return View((object)viewModel); } - public ActionResult Item(int blogId, Pager pager) { + public ActionResult Item(int blogId, PagerParameters pagerParameters) { + Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); BlogPart blogPart = _blogService.Get(blogId, VersionOptions.Latest).As(); if (blogPart == null) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs index 5661a51ce..43a78d750 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogController.cs @@ -13,6 +13,8 @@ using Orchard.Themes; using Orchard.UI.Navigation; namespace Orchard.Blogs.Controllers { + using Orchard.Settings; + [Themed] public class BlogController : Controller { private readonly IOrchardServices _services; @@ -22,6 +24,7 @@ namespace Orchard.Blogs.Controllers { private readonly IFeedManager _feedManager; private readonly IWorkContextAccessor _workContextAccessor; private readonly IHomePageProvider _routableHomePageProvider; + private readonly ISiteService _siteService; public BlogController( IOrchardServices services, @@ -31,13 +34,15 @@ namespace Orchard.Blogs.Controllers { IFeedManager feedManager, IShapeFactory shapeFactory, IWorkContextAccessor workContextAccessor, - IEnumerable homePageProviders) { + IEnumerable homePageProviders, + ISiteService siteService) { _services = services; _blogService = blogService; _blogPostService = blogPostService; _blogSlugConstraint = blogSlugConstraint; _feedManager = feedManager; _workContextAccessor = workContextAccessor; + _siteService = siteService; _routableHomePageProvider = homePageProviders.SingleOrDefault(p => p.GetProviderName() == RoutableHomePageProvider.Name); Logger = NullLogger.Instance; Shape = shapeFactory; @@ -59,7 +64,8 @@ namespace Orchard.Blogs.Controllers { return View((object)viewModel); } - public ActionResult Item(string blogSlug, Pager pager) { + public ActionResult Item(string blogSlug, PagerParameters pagerParameters) { + Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); var correctedSlug = _blogSlugConstraint.FindSlug(blogSlug); if (correctedSlug == null) return HttpNotFound(); diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs index d60e3e56d..47bfce9df 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs @@ -9,6 +9,8 @@ using Orchard.ContentManagement.Aspects; using Orchard.Core.Contents.Settings; using Orchard.Localization; using Orchard.Mvc.AntiForgery; +using Orchard.Security; +using Orchard.Security.Permissions; using Orchard.UI.Admin; using Orchard.UI.Notify; @@ -84,9 +86,6 @@ namespace Orchard.Blogs.Controllers { //todo: the content shape template has extra bits that the core contents module does not (remove draft functionality) //todo: - move this extra functionality there or somewhere else that's appropriate? public ActionResult Edit(int blogId, int postId) { - if (!Services.Authorizer.Authorize(Permissions.EditOwnBlogPost, T("Couldn't edit blog post"))) - return new HttpUnauthorizedResult(); - var blog = _blogService.Get(blogId, VersionOptions.Latest); if (blog == null) return HttpNotFound(); @@ -95,6 +94,9 @@ namespace Orchard.Blogs.Controllers { if (post == null) return HttpNotFound(); + if (!Services.Authorizer.Authorize(Permissions.EditOthersBlogPost, post.ContentItem, T("Couldn't edit blog post"))) + return new HttpUnauthorizedResult(); + dynamic model = Services.ContentManager.BuildEditor(post); // 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/Modules/Orchard.Blogs/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Migrations.cs index 90e71d88d..1fc750a75 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Migrations.cs @@ -5,7 +5,7 @@ namespace Orchard.Blogs { public class Migrations : DataMigrationImpl { public int Create() { - SchemaBuilder.CreateTable("BlogPartArchiveRecord", + SchemaBuilder.CreateTable("BlogPartArchiveRecord", table => table .Column("Id", column => column.PrimaryKey().Identity()) .Column("Year") @@ -14,21 +14,21 @@ namespace Orchard.Blogs { .Column("BlogPart_id") ); - SchemaBuilder.CreateTable("BlogPartRecord", + SchemaBuilder.CreateTable("BlogPartRecord", table => table .ContentPartRecord() .Column("Description", c => c.Unlimited()) .Column("PostCount") ); - SchemaBuilder.CreateTable("RecentBlogPostsPartRecord", + SchemaBuilder.CreateTable("RecentBlogPostsPartRecord", table => table .ContentPartRecord() .Column("BlogSlug") .Column("Count") ); - SchemaBuilder.CreateTable("BlogArchivesPartRecord", + SchemaBuilder.CreateTable("BlogArchivesPartRecord", table => table .ContentPartRecord() .Column("BlogSlug", c => c.WithLength(255)) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj b/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj index 485adb414..2283d6feb 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Orchard.Blogs.csproj @@ -82,6 +82,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Security/BlogAuthorizationEventHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Security/BlogAuthorizationEventHandler.cs new file mode 100644 index 000000000..fb0585f71 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Security/BlogAuthorizationEventHandler.cs @@ -0,0 +1,49 @@ +using JetBrains.Annotations; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.Security; +using Orchard.Security.Permissions; + +namespace Orchard.Blogs.Security { + [UsedImplicitly] + public class BlogAuthorizationEventHandler : IAuthorizationServiceEventHandler { + public void Checking(CheckAccessContext context) { } + public void Complete(CheckAccessContext context) { } + + public void Adjust(CheckAccessContext context) { + if (!context.Granted && + context.Content.Is()) { + if (OwnerVariationExists(context.Permission) && + HasOwnership(context.User, context.Content)) { + context.Adjusted = true; + context.Permission = GetOwnerVariation(context.Permission); + } + } + } + + private static bool HasOwnership(IUser user, IContent content) { + if (user == null || content == null) + return false; + + var common = content.As(); + if (common == null || common.Owner == null) + return false; + + return user.Id == common.Owner.Id; + } + + private static bool OwnerVariationExists(Permission permission) { + return GetOwnerVariation(permission) != null; + } + + private static Permission GetOwnerVariation(Permission permission) { + if (permission.Name == Permissions.PublishOthersBlogPost.Name) + return Permissions.PublishOwnBlogPost; + if (permission.Name == Permissions.EditOthersBlogPost.Name) + return Permissions.EditOwnBlogPost; + if (permission.Name == Permissions.DeleteOthersBlogPost.Name) + return Permissions.DeleteOwnBlogPost; + return null; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs index bd48b5c8a..616086921 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs @@ -123,7 +123,7 @@ namespace Orchard.Blogs.Services { string password) { var user = _membershipService.ValidateUser(userName, password); - _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); + _authorizationService.CheckAccess(Permissions.EditOthersBlogPost, user, null); var array = new XRpcArray(); foreach (var blog in _blogService.Get()) { @@ -144,7 +144,7 @@ namespace Orchard.Blogs.Services { int numberOfPosts) { var user = _membershipService.ValidateUser(userName, password); - _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); + _authorizationService.CheckAccess(Permissions.EditOthersBlogPost, user, null); var blog = _contentManager.Get(Convert.ToInt32(blogId)); if (blog == null) @@ -166,7 +166,7 @@ namespace Orchard.Blogs.Services { IEnumerable drivers) { var user = _membershipService.ValidateUser(userName, password); - _authorizationService.CheckAccess(Permissions.EditOwnBlogPost, user, null); + _authorizationService.CheckAccess(publish ? Permissions.PublishOthersBlogPost : Permissions.EditOthersBlogPost, user, null); var blog = _contentManager.Get(Convert.ToInt32(blogId)); if (blog == null) @@ -216,7 +216,7 @@ namespace Orchard.Blogs.Services { IEnumerable drivers) { var user = _membershipService.ValidateUser(userName, password); - _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); + _authorizationService.CheckAccess(Permissions.EditOthersBlogPost, user, null); var blogPost = _blogPostService.Get(postId, VersionOptions.Latest); if (blogPost == null) @@ -231,15 +231,13 @@ namespace Orchard.Blogs.Services { } private bool MetaWeblogEditPost(int postId, string userName, string password, XRpcStruct content, bool publish, IEnumerable drivers) { - var user = _membershipService.ValidateUser(userName, password); - _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); + _authorizationService.CheckAccess(publish ? Permissions.PublishOthersBlogPost : Permissions.EditOthersBlogPost, user, null); var blogPost = _blogPostService.Get(postId, VersionOptions.DraftRequired); if (blogPost == null) throw new ArgumentException(); - var title = content.Optional("title"); var description = content.Optional("description"); var slug = content.Optional("wp_slug"); @@ -259,7 +257,7 @@ namespace Orchard.Blogs.Services { private bool MetaWeblogDeletePost(string appkey, string postId, string userName, string password, bool publish, IEnumerable drivers) { var user = _membershipService.ValidateUser(userName, password); - _authorizationService.CheckAccess(StandardPermissions.AccessFrontEnd, user, null); + _authorizationService.CheckAccess(Permissions.DeleteOthersBlogPost, user, null); var blogPost = _blogPostService.Get(Convert.ToInt32(postId), VersionOptions.Latest); if (blogPost == null) diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs index c5164d4ad..69d543b72 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs @@ -14,12 +14,20 @@ using Orchard.Comments.ViewModels; using Orchard.Comments.Services; namespace Orchard.Comments.Controllers { + using Orchard.Settings; + [ValidateInput(false)] public class AdminController : Controller { private readonly ICommentService _commentService; + private readonly ISiteService _siteService; - public AdminController(IOrchardServices services, ICommentService commentService, IShapeFactory shapeFactory) { + public AdminController( + IOrchardServices services, + ICommentService commentService, + ISiteService siteService, + IShapeFactory shapeFactory) { _commentService = commentService; + _siteService = siteService; Services = services; Logger = NullLogger.Instance; T = NullLocalizer.Instance; @@ -31,7 +39,9 @@ namespace Orchard.Comments.Controllers { public Localizer T { get; set; } dynamic Shape { get; set; } - public ActionResult Index(CommentIndexOptions options, Pager pager) { + public ActionResult Index(CommentIndexOptions options, PagerParameters pagerParameters) { + Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); + // Default options if (options == null) options = new CommentIndexOptions(); diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Styles/orchard-comments-admin.css b/src/Orchard.Web/Modules/Orchard.Comments/Styles/orchard-comments-admin.css index 23bd8bd41..4138d1b3d 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Styles/orchard-comments-admin.css +++ b/src/Orchard.Web/Modules/Orchard.Comments/Styles/orchard-comments-admin.css @@ -2,7 +2,7 @@ white-space:nowrap; } table.items tr { - background:#f7f7f7; + background:#fff; } table.items tr.anonymous { background:#fff; diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs index 6fdb834a1..dcf88ab96 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs @@ -36,7 +36,7 @@ namespace Orchard.ContentTypes.Services { public Localizer T { get; set; } public IEnumerable GetTypes() { - return _contentDefinitionManager.ListTypeDefinitions().Select(ctd => new EditTypeViewModel(ctd)); + return _contentDefinitionManager.ListTypeDefinitions().Select(ctd => new EditTypeViewModel(ctd)).OrderBy(m => m.DisplayName); } public EditTypeViewModel GetType(string name) { diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Styles/orchard-contenttypes-admin.css b/src/Orchard.Web/Modules/Orchard.ContentTypes/Styles/orchard-contenttypes-admin.css index c4c3f0c7d..235b2adaa 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Styles/orchard-contenttypes-admin.css +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Styles/orchard-contenttypes-admin.css @@ -1,5 +1,6 @@ .orchard-contenttypes #main h2 { margin:1.5em 0 0; + border-bottom:1px solid #ccc; } #main .properties p { diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.Packaging/AdminMenu.cs index f34d93011..fbfe5565b 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/AdminMenu.cs @@ -1,6 +1,7 @@ using Orchard.Environment.Extensions; using Orchard.Localization; using Orchard.UI.Navigation; +using Orchard.Security; namespace Orchard.Packaging { [OrchardFeature("Gallery")] @@ -12,11 +13,14 @@ namespace Orchard.Packaging { public void GetNavigation(NavigationBuilder builder) { builder.Add(T("Gallery"), "30", menu => menu .Add(T("Modules"), "1.0", item => item - .Action("Modules", "Gallery", new { area = "Orchard.Packaging" })) + .Action("Modules", "Gallery", new { area = "Orchard.Packaging" }) + .Permission(StandardPermissions.SiteOwner)) .Add(T("Themes"), "2.0", item => item - .Action("Themes", "Gallery", new { area = "Orchard.Packaging" })) + .Action("Themes", "Gallery", new { area = "Orchard.Packaging" }) + .Permission(StandardPermissions.SiteOwner)) .Add(T("Feeds"), "3.0", item => item - .Action("Sources", "Gallery", new { area = "Orchard.Packaging" }))); + .Action("Sources", "Gallery", new { area = "Orchard.Packaging" }) + .Permission(StandardPermissions.SiteOwner))); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs index 57654a990..c07eecccf 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryController.cs @@ -9,6 +9,7 @@ using Orchard.Localization; using Orchard.Logging; using Orchard.Packaging.Services; using Orchard.Packaging.ViewModels; +using Orchard.Security; using Orchard.Themes; using Orchard.UI.Admin; using Orchard.UI.Notify; @@ -26,36 +27,51 @@ namespace Orchard.Packaging.Controllers { public GalleryController( IPackageManager packageManager, IPackagingSourceManager packagingSourceManager, - INotifier notifier) { + INotifier notifier, + IOrchardServices services) { _packageManager = packageManager; _packagingSourceManager = packagingSourceManager; _notifier = notifier; + Services = services; T = NullLocalizer.Instance; Logger = NullLogger.Instance; } + public IOrchardServices Services { get; set; } public Localizer T { get; set; } public ILogger Logger { get; set; } public ActionResult Sources() { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list sources"))) + return new HttpUnauthorizedResult(); + return View(new PackagingSourcesViewModel { Sources = _packagingSourceManager.GetSources(), }); } public ActionResult Remove(int id) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to remove sources"))) + return new HttpUnauthorizedResult(); + _packagingSourceManager.RemoveSource(id); _notifier.Information(T("The feed has been removed successfully.")); return RedirectToAction("Sources"); } public ActionResult AddSource() { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add sources"))) + return new HttpUnauthorizedResult(); + return View(new PackagingAddSourceViewModel()); } [HttpPost] public ActionResult AddSource(string url) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add sources"))) + return new HttpUnauthorizedResult(); + try { if (!String.IsNullOrEmpty(url)) { if (!url.StartsWith("http")) { @@ -96,6 +112,9 @@ namespace Orchard.Packaging.Controllers { } public ActionResult Modules(int? sourceId) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list modules"))) + return new HttpUnauthorizedResult(); + var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault(); var sources = selectedSource != null @@ -123,6 +142,9 @@ namespace Orchard.Packaging.Controllers { } public ActionResult Themes(int? sourceId) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list themes"))) + return new HttpUnauthorizedResult(); + var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault(); var sources = selectedSource != null @@ -138,6 +160,9 @@ namespace Orchard.Packaging.Controllers { } public ActionResult Install(string packageId, string version, int sourceId, string redirectTo) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to install packages"))) + return new HttpUnauthorizedResult(); + var source = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault(); if (source == null) { diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/PackagingServicesController.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/PackagingServicesController.cs index e51d385f1..1686dcfb3 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/PackagingServicesController.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/PackagingServicesController.cs @@ -8,6 +8,7 @@ using Orchard.Environment.Extensions; using Orchard.FileSystems.AppData; using Orchard.Localization; using Orchard.Packaging.Services; +using Orchard.Security; using Orchard.Themes; using Orchard.UI.Admin; using Orchard.UI.Notify; @@ -25,40 +26,61 @@ namespace Orchard.Packaging.Controllers { public PackagingServicesController( IPackageManager packageManager, INotifier notifier, - IAppDataFolderRoot appDataFolderRoot) { + IAppDataFolderRoot appDataFolderRoot, + IOrchardServices services) { _packageManager = packageManager; _notifier = notifier; _appDataFolderRoot = appDataFolderRoot; + Services = services; T = NullLocalizer.Instance; } public Localizer T { get; set; } + public IOrchardServices Services { get; set; } public ActionResult AddTheme(string returnUrl) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add themes"))) + return new HttpUnauthorizedResult(); + return View(); } [HttpPost, ActionName("AddTheme")] public ActionResult AddThemePOST(string returnUrl) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add themes"))) + return new HttpUnauthorizedResult(); + return InstallPackage(returnUrl, Request.RawUrl); } [HttpPost, ActionName("RemoveTheme")] public ActionResult RemoveThemePOST(string themeId, string returnUrl, string retryUrl) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to remove themes"))) + return new HttpUnauthorizedResult(); + return UninstallPackage(PackagingSourceManager.ThemesPrefix + themeId, returnUrl, retryUrl); } public ActionResult AddModule(string returnUrl) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add modules"))) + return new HttpUnauthorizedResult(); + return View(); } [HttpPost, ActionName("AddModule")] public ActionResult AddModulePOST(string returnUrl) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add modules"))) + return new HttpUnauthorizedResult(); + return InstallPackage(returnUrl, Request.RawUrl); } public ActionResult InstallPackage(string returnUrl, string retryUrl) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to install packages"))) + return new HttpUnauthorizedResult(); + try { if (Request.Files != null && Request.Files.Count > 0 && @@ -90,6 +112,9 @@ namespace Orchard.Packaging.Controllers { } public ActionResult UninstallPackage(string id, string returnUrl, string retryUrl) { + if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to uninstall packages"))) + return new HttpUnauthorizedResult(); + try { _packageManager.Uninstall(id, HostingEnvironment.MapPath("~/")); diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Drivers/PublishLaterPartDriver.cs b/src/Orchard.Web/Modules/Orchard.PublishLater/Drivers/PublishLaterPartDriver.cs index 492f0b1b0..78a3d8789 100644 --- a/src/Orchard.Web/Modules/Orchard.PublishLater/Drivers/PublishLaterPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Drivers/PublishLaterPartDriver.cs @@ -2,6 +2,7 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.Core.Common.Services; +using Orchard.Mvc; using Orchard.PublishLater.Models; using Orchard.PublishLater.Services; using Orchard.PublishLater.ViewModels; @@ -58,22 +59,24 @@ namespace Orchard.PublishLater.Drivers { updater.TryUpdateModel(model, Prefix, null, null); - if (!string.IsNullOrWhiteSpace(model.ScheduledPublishDate) && !string.IsNullOrWhiteSpace(model.ScheduledPublishTime)) { - DateTime scheduled; - string parseDateTime = String.Concat(model.ScheduledPublishDate, " ", model.ScheduledPublishTime); + if (Services.WorkContext.Resolve().Current().Request.Form["submit.Save"] == "submit.PublishLater") { + if (!string.IsNullOrWhiteSpace(model.ScheduledPublishDate) && !string.IsNullOrWhiteSpace(model.ScheduledPublishTime)) { + DateTime scheduled; + string parseDateTime = String.Concat(model.ScheduledPublishDate, " ", model.ScheduledPublishTime); - // use an english culture as it is the one used by jQuery.datepicker by default - if (DateTime.TryParse(parseDateTime, CultureInfo.GetCultureInfo("en-US"), DateTimeStyles.AssumeLocal, out scheduled)) { - model.ScheduledPublishUtc = part.ScheduledPublishUtc.Value = scheduled.ToUniversalTime(); - _publishLaterService.Publish(model.ContentItem, model.ScheduledPublishUtc.Value); + // use an english culture as it is the one used by jQuery.datepicker by default + if (DateTime.TryParse(parseDateTime, CultureInfo.GetCultureInfo("en-US"), DateTimeStyles.AssumeLocal, out scheduled)) { + model.ScheduledPublishUtc = part.ScheduledPublishUtc.Value = scheduled.ToUniversalTime(); + _publishLaterService.Publish(model.ContentItem, model.ScheduledPublishUtc.Value); + } + else { + updater.AddModelError(Prefix, T("{0} is an invalid date and time", parseDateTime)); + } } - else { - updater.AddModelError(Prefix, T("{0} is an invalid date and time", parseDateTime)); + else if (!string.IsNullOrWhiteSpace(model.ScheduledPublishDate) || !string.IsNullOrWhiteSpace(model.ScheduledPublishTime)) { + updater.AddModelError(Prefix, T("Both the date and time need to be specified for when this is to be published. If you don't want to schedule publishing then click Save or Publish Now.")); } } - else if (!string.IsNullOrWhiteSpace(model.ScheduledPublishDate) || !string.IsNullOrWhiteSpace(model.ScheduledPublishTime)) { - updater.AddModelError(Prefix, T("Both the date and time need to be specified for when this is to be published. If you don't want to schedule publishing then clear both the date and time fields.")); - } return ContentShape("Parts_PublishLater_Edit", () => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: model, Prefix: Prefix)); diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Placement.info b/src/Orchard.Web/Modules/Orchard.PublishLater/Placement.info index 540beb062..44407210b 100644 --- a/src/Orchard.Web/Modules/Orchard.PublishLater/Placement.info +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Placement.info @@ -7,7 +7,7 @@ --> - + diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Styles/orchard-publishlater-datetime.css b/src/Orchard.Web/Modules/Orchard.PublishLater/Styles/orchard-publishlater-datetime.css index af6b87158..3ada88ce5 100644 --- a/src/Orchard.Web/Modules/Orchard.PublishLater/Styles/orchard-publishlater-datetime.css +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Styles/orchard-publishlater-datetime.css @@ -6,9 +6,25 @@ html.dyn input.hinted { color:#ccc; font-style:italic; } + +fieldset.publish-later-datetime { + float:left; + clear:none; + white-space: nowrap; + vertical-align: middle; +} +fieldset.publish-later-datetime legend { + display:none; +} +fieldset.publish-later-datetime input { + padding:1px; + text-align:center; + color:#666; +} + input#PublishLater_ScheduledPublishDate { - width:49%; + width:39%; } input#PublishLater_ScheduledPublishTime { - width:43%; -} \ No newline at end of file + width:33%; +} diff --git a/src/Orchard.Web/Modules/Orchard.PublishLater/Views/EditorTemplates/Parts/PublishLater.cshtml b/src/Orchard.Web/Modules/Orchard.PublishLater/Views/EditorTemplates/Parts/PublishLater.cshtml index d0678e18b..ab6ad2dfa 100644 --- a/src/Orchard.Web/Modules/Orchard.PublishLater/Views/EditorTemplates/Parts/PublishLater.cshtml +++ b/src/Orchard.Web/Modules/Orchard.PublishLater/Views/EditorTemplates/Parts/PublishLater.cshtml @@ -12,6 +12,7 @@ @Html.EditorFor(m => m.ScheduledPublishDate) @Html.EditorFor(m => m.ScheduledPublishTime) + @using(Script.Foot()) {