Merge branch '1.10.x' into dev

# Conflicts:
#	src/Orchard.Web/Core/Contents/Controllers/AdminController.cs
#	src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library.js
This commit is contained in:
Benedek Farkas 2019-08-13 17:38:13 +02:00
commit bbc86d38cd
33 changed files with 587 additions and 264 deletions

View File

@ -30,7 +30,11 @@ namespace Orchard.Core.Common {
.Column<DateTime>("PublishedUtc")
.Column<DateTime>("ModifiedUtc")
.Column<int>("Container_id")
);
).AlterTable(nameof(CommonPartRecord), table => {
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_{nameof(CommonPartRecord.CreatedUtc)}", nameof(CommonPartRecord.CreatedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_{nameof(CommonPartRecord.ModifiedUtc)}", nameof(CommonPartRecord.ModifiedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_{nameof(CommonPartRecord.PublishedUtc)}", nameof(CommonPartRecord.PublishedUtc));
});
SchemaBuilder.CreateTable("CommonPartVersionRecord",
table => table
@ -39,7 +43,11 @@ namespace Orchard.Core.Common {
.Column<DateTime>("PublishedUtc")
.Column<DateTime>("ModifiedUtc")
.Column<string>("ModifiedBy")
);
).AlterTable(nameof(CommonPartVersionRecord), table => {
table.CreateIndex($"IDX_{nameof(CommonPartVersionRecord)}_{nameof(CommonPartVersionRecord.CreatedUtc)}", nameof(CommonPartVersionRecord.CreatedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartVersionRecord)}_{nameof(CommonPartVersionRecord.ModifiedUtc)}", nameof(CommonPartVersionRecord.ModifiedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartVersionRecord)}_{nameof(CommonPartVersionRecord.PublishedUtc)}", nameof(CommonPartVersionRecord.PublishedUtc));
});
SchemaBuilder.CreateTable("IdentityPartRecord",
table => table
@ -59,7 +67,7 @@ namespace Orchard.Core.Common {
.Attachable()
.WithDescription("Automatically generates a unique identity for the content item, which is required in import/export scenarios where one content item references another."));
return 5;
return 6;
}
public int UpdateFrom1() {
@ -112,5 +120,21 @@ namespace Orchard.Core.Common {
SchemaBuilder.AlterTable("CommonPartVersionRecord", table => table.AddColumn<string>("ModifiedBy", command => command.Nullable()));
return 5;
}
public int UpdateFrom5() {
SchemaBuilder.AlterTable(nameof(CommonPartRecord), table => {
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_{nameof(CommonPartRecord.CreatedUtc)}", nameof(CommonPartRecord.CreatedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_{nameof(CommonPartRecord.ModifiedUtc)}", nameof(CommonPartRecord.ModifiedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_{nameof(CommonPartRecord.PublishedUtc)}", nameof(CommonPartRecord.PublishedUtc));
});
SchemaBuilder.AlterTable(nameof(CommonPartVersionRecord), table => {
table.CreateIndex($"IDX_{nameof(CommonPartVersionRecord)}_{nameof(CommonPartVersionRecord.CreatedUtc)}", nameof(CommonPartVersionRecord.CreatedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartVersionRecord)}_{nameof(CommonPartVersionRecord.ModifiedUtc)}", nameof(CommonPartVersionRecord.ModifiedUtc));
table.CreateIndex($"IDX_{nameof(CommonPartVersionRecord)}_{nameof(CommonPartVersionRecord.PublishedUtc)}", nameof(CommonPartVersionRecord.PublishedUtc));
});
return 6;
}
}
}

View File

@ -14,20 +14,19 @@ using Orchard.Core.Containers.Models;
using Orchard.Core.Contents.Settings;
using Orchard.Core.Contents.ViewModels;
using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Localization.Services;
using Orchard.Logging;
using Orchard.Mvc.Extensions;
using Orchard.Mvc.Html;
using Orchard.Settings;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
using Orchard.Settings;
using Orchard.Utility.Extensions;
using Orchard.Localization.Services;
namespace Orchard.Core.Contents.Controllers {
[ValidateInput(false)]
public class AdminController : Controller, IUpdateModel {
public class AdminController : ContentControllerBase, IUpdateModel {
private readonly IContentManager _contentManager;
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly ITransactionManager _transactionManager;
@ -37,24 +36,21 @@ namespace Orchard.Core.Contents.Controllers {
public AdminController(
IOrchardServices orchardServices,
IContentManager contentManager,
IContentDefinitionManager contentDefinitionManager,
ITransactionManager transactionManager,
ISiteService siteService,
IShapeFactory shapeFactory,
ICultureManager cultureManager,
ICultureFilter cultureFilter) {
ICultureFilter cultureFilter) : base(orchardServices.ContentManager) {
Services = orchardServices;
_contentManager = contentManager;
_contentManager = orchardServices.ContentManager;
_transactionManager = orchardServices.TransactionManager;
_contentDefinitionManager = contentDefinitionManager;
_transactionManager = transactionManager;
_siteService = siteService;
_cultureManager = cultureManager;
_cultureFilter = cultureFilter;
T = NullLocalizer.Instance;
Logger = NullLogger.Instance;
Shape = shapeFactory;
Shape = orchardServices.New;
}
dynamic Shape { get; set; }
@ -248,6 +244,11 @@ namespace Orchard.Core.Contents.Controllers {
var contentItem = _contentManager.New(id);
var customRouteRedirection = GetCustomContentItemRouteRedirection(contentItem, ContentItemRoute.Create);
if (customRouteRedirection != null) {
return customRouteRedirection;
}
if (!Services.Authorizer.Authorize(Permissions.CreateContent, contentItem, T("Cannot create content")))
return new HttpUnauthorizedResult();
@ -323,6 +324,11 @@ namespace Orchard.Core.Contents.Controllers {
public ActionResult Edit(int id) {
var contentItem = _contentManager.Get(id, VersionOptions.Latest);
var customRouteRedirection = GetCustomContentItemRouteRedirection(contentItem, ContentItemRoute.Editor);
if (customRouteRedirection != null) {
return customRouteRedirection;
}
if (contentItem == null)
return HttpNotFound();
@ -416,6 +422,10 @@ namespace Orchard.Core.Contents.Controllers {
// pass a dummy content to the authorization check to check for "own" variations
var dummyContent = _contentManager.New(originalContentItem.ContentType);
if (!Services.Authorizer.Authorize(Permissions.EditContent, dummyContent, T("You do not have permission to edit (or create) content.")))
return new HttpUnauthorizedResult();
if (!Services.Authorizer.Authorize(Permissions.EditContent, dummyContent, T("You do not have permission to edit (or create) content.")))
return new HttpUnauthorizedResult();

View File

@ -0,0 +1,52 @@
using System;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.ContentManagement;
using Orchard.Mvc.Extensions;
namespace Orchard.Core.Contents.Controllers {
public abstract class ContentControllerBase : Controller {
private readonly IContentManager _contentManager;
public ContentControllerBase(IContentManager contentManager) {
_contentManager = contentManager;
}
public RedirectToRouteResult GetCustomContentItemRouteRedirection(IContent content, ContentItemRoute contentItemRoute) {
if (content == null) return null;
var itemMetadata = _contentManager.GetItemMetadata(content);
var currentRoute = RouteData.Values;
bool isCustomRoute(RouteValueDictionary routeValues) =>
!currentRoute.ToRouteString().Equals(routeValues.ToRouteString(), StringComparison.InvariantCultureIgnoreCase);
switch (contentItemRoute) {
case ContentItemRoute.Admin:
if (isCustomRoute(itemMetadata.AdminRouteValues))
return RedirectToRoute(itemMetadata.AdminRouteValues);
break;
case ContentItemRoute.Editor:
if (isCustomRoute(itemMetadata.EditorRouteValues))
return RedirectToRoute(itemMetadata.EditorRouteValues);
break;
case ContentItemRoute.Create:
if (isCustomRoute(itemMetadata.CreateRouteValues))
return RedirectToRoute(itemMetadata.CreateRouteValues);
break;
case ContentItemRoute.Display:
if (isCustomRoute(itemMetadata.DisplayRouteValues))
return RedirectToRoute(itemMetadata.DisplayRouteValues);
break;
}
return null;
}
}
}

View File

@ -1,28 +1,25 @@
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc;
using Orchard.Themes;
namespace Orchard.Core.Contents.Controllers {
[Themed]
public class ItemController : Controller {
public class ItemController : ContentControllerBase {
private readonly IContentManager _contentManager;
private readonly IHttpContextAccessor _hca;
public ItemController(IContentManager contentManager,
IShapeFactory shapeFactory,
IOrchardServices services,
IHttpContextAccessor hca) {
_contentManager = contentManager;
public ItemController(
IOrchardServices orchardServices,
IHttpContextAccessor hca) : base(orchardServices.ContentManager) {
_contentManager = orchardServices.ContentManager;
_hca = hca;
Shape = shapeFactory;
Services = services;
Services = orchardServices;
T = NullLocalizer.Instance;
}
dynamic Shape { get; set; }
public IOrchardServices Services { get; private set; }
public Localizer T { get; set; }
@ -36,16 +33,21 @@ namespace Orchard.Core.Contents.Controllers {
var contentItem = _contentManager.Get(id.Value, VersionOptions.Published);
var customRouteRedirection = GetCustomContentItemRouteRedirection(contentItem, ContentItemRoute.Display);
if (customRouteRedirection != null) {
return customRouteRedirection;
}
if (contentItem == null)
return HttpNotFound();
if (!Services.Authorizer.Authorize(Permissions.ViewContent, contentItem, T("Cannot view content"))) {
return new HttpUnauthorizedResult();
}
var model = _contentManager.BuildDisplay(contentItem);
if (_hca.Current().Request.IsAjaxRequest()) {
return new ShapePartialResult(this,model);
return new ShapePartialResult(this, model);
}
return View(model);

View File

@ -1,5 +1,26 @@
@{ Layout.Title = T("Create New Content").ToString(); }
@using Orchard;
@using Orchard.ContentManagement;
@using Orchard.Core.Contents;
@{
IOrchardServices _orchardServices;
WorkContext.TryResolve<IOrchardServices>(out _orchardServices);
Layout.Title = T("Create New Content");
}
@foreach (var type in Model.ContentTypes) {
<p>@Html.ActionLink((string)type.DisplayName, "Create", new { Area = "Contents", Id = (string)type.Name, ContainerId = Model.ContainerId, ReturnUrl = Request.QueryString["ReturnUrl"] })</p>
var content = _orchardServices.ContentManager.New(type.Name);
if (Authorizer.Authorize(Permissions.CreateContent, content)) {
ContentItemMetadata metadata = _orchardServices.ContentManager.GetItemMetadata(content);
RouteValueDictionary createRouteValues = metadata.CreateRouteValues;
createRouteValues.Add("ContainerId", Model.ContainerId);
createRouteValues.Add("ReturnUrl", Request.QueryString["ReturnUrl"]);
var url = Url.RouteUrl(createRouteValues);
<p><a href="@url">@type.DisplayName</a></p>
}
}

View File

@ -1,13 +1,18 @@
@using Orchard.Core.Contents;
@using Orchard;
@using Orchard.ContentManagement;
@using Orchard.Core.Contents;
@using Orchard.Core.Contents.ViewModels;
@using Orchard.Security;
@using Orchard.Security.Permissions;
@{
IOrchardServices _orchardServices;
WorkContext.TryResolve<IOrchardServices>(out _orchardServices);
var typeDisplayName = Model.TypeDisplayName;
var pageTitle = T("Manage Content");
var createLinkText = T("Create New Content");
// if no specific type is selected, we assume we should show the "Create" button
var showCreateContentButton = string.IsNullOrWhiteSpace(typeDisplayName);
var showCreateContentButton = string.IsNullOrWhiteSpace(typeDisplayName);
IAuthorizationService _authorizationService;
WorkContext.TryResolve<IAuthorizationService>(out _authorizationService);
@ -26,9 +31,19 @@
Layout.Title = pageTitle.Text;
}
@if (showCreateContentButton) {
@if (showCreateContentButton) {
<div class="manage">
@Html.ActionLink(createLinkText.Text, "Create", new { Area = "Contents", Id = (string)Model.Options.SelectedFilter }, new { @class = "button primaryAction" })
@{
if (!String.IsNullOrWhiteSpace((string)Model.Options.SelectedFilter)) {
var content = _orchardServices.ContentManager.New(Model.Options.SelectedFilter);
ContentItemMetadata metadata = _orchardServices.ContentManager.GetItemMetadata(content);
var url = Url.RouteUrl(metadata.CreateRouteValues);
<a class="button primaryAction" href="@url">@createLinkText.Text</a>
} else {
@Html.ActionLink(createLinkText.Text, "Create", new { Area = "Contents", Id = (string)Model.Options.SelectedFilter }, new { @class = "button primaryAction" });
}
}
</div>
}
@using (Html.BeginFormAntiForgeryPost()) {

View File

@ -153,6 +153,7 @@
<Compile Include="Containers\ViewModels\ContainerViewModel.cs" />
<Compile Include="Containers\ViewModels\ContainerTypePartSettingsViewModel.cs" />
<Compile Include="Containers\ViewModels\ContainerWidgetViewModel.cs" />
<Compile Include="Contents\Controllers\ContentControllerBase.cs" />
<Compile Include="Contents\ControlWrapper.cs" />
<Compile Include="Contents\Security\AuthorizationEventHandler.cs" />
<Compile Include="Common\Services\BbcodeFilter.cs" />

View File

@ -17,88 +17,87 @@ namespace Orchard.Autoroute {
}
public int Create() {
SchemaBuilder.CreateTable("AutoroutePartRecord",
table => table
.ContentPartVersionRecord()
.Column<string>("CustomPattern", c => c.WithLength(2048))
.Column<bool>("UseCustomPattern", c => c.WithDefault(false))
.Column<bool>("UseCulturePattern", c => c.WithDefault(false))
.Column<string>("DisplayAlias", c => c.WithLength(2048)));
SchemaBuilder.CreateTable("AutoroutePartRecord", table => table
.ContentPartVersionRecord()
.Column<string>("CustomPattern", c => c.WithLength(2048))
.Column<bool>("UseCustomPattern", c => c.WithDefault(false))
.Column<bool>("UseCulturePattern", c => c.WithDefault(false))
.Column<string>("DisplayAlias", c => c.WithLength(2048)));
ContentDefinitionManager.AlterPartDefinition("AutoroutePart", part => part
.Attachable()
.WithDescription("Adds advanced url configuration options to your content type to completely customize the url pattern for a content item."));
SchemaBuilder.AlterTable("AutoroutePartRecord", table => table
.CreateIndex("IDX_AutoroutePartRecord_DisplayAlias", "DisplayAlias")
);
.CreateIndex("IDX_AutoroutePartRecord_DisplayAlias", "DisplayAlias"));
return 4;
CreateCulturePatterns();
return 5;
}
public int UpdateFrom1() {
ContentDefinitionManager.AlterPartDefinition("AutoroutePart", part => part
.WithDescription("Adds advanced url configuration options to your content type to completely customize the url pattern for a content item."));
return 2;
}
public int UpdateFrom2() {
SchemaBuilder.AlterTable("AutoroutePartRecord", table => table
.CreateIndex("IDX_AutoroutePartRecord_DisplayAlias", "DisplayAlias")
);
.CreateIndex("IDX_AutoroutePartRecord_DisplayAlias", "DisplayAlias"));
return 3;
}
public int UpdateFrom3() {
SchemaBuilder.AlterTable("AutoroutePartRecord", table => table
.AddColumn<bool>("UseCulturePattern", c => c.WithDefault(false))
);
.AddColumn<bool>("UseCulturePattern", c => c.WithDefault(false)));
return 4;
}
public int UpdateFrom4() {
// Adding some culture neutral patterns if they don't exist
var autoroutePartDefinitions = ContentDefinitionManager.ListTypeDefinitions()
.Where(t => t.Parts.Any(p => p.PartDefinition.Name.Equals(typeof(AutoroutePart).Name)))
.Select(s => new { contentTypeName = s.Name, autoroutePart = s.Parts.First(x => x.PartDefinition.Name == "AutoroutePart") });
foreach (var partDefinition in autoroutePartDefinitions) {
var settingsDictionary = partDefinition.autoroutePart.Settings;
var settings = settingsDictionary.GetModel<AutorouteSettings>();
if (!settings.Patterns.Any(x => String.IsNullOrWhiteSpace(x.Culture))) {
string siteCulture = _cultureManager.GetSiteCulture();
List<string> newPatterns = new List<string>();
if (settings.Patterns.Any(x => String.Equals(x.Culture, siteCulture, StringComparison.OrdinalIgnoreCase))) {
var siteCulturePatterns = settings.Patterns.Where(x => String.Equals(x.Culture, siteCulture, StringComparison.OrdinalIgnoreCase)).ToList();
foreach (RoutePattern pattern in siteCulturePatterns) {
newPatterns.Add(String.Format("{{\"Name\":\"{0}\",\"Pattern\":\"{1}\",\"Description\":\"{2}\"}}", pattern.Name, pattern.Pattern, pattern.Description));
}
}
else {
newPatterns.Add(String.Format("{{\"Name\":\"{0}\",\"Pattern\":\"{1}\",\"Description\":\"{2}\"}}", "Title", "{Content.Slug}", "my-title"));
}
if (settingsDictionary.ContainsKey("AutorouteSettings.PatternDefinitions")) {
string oldPatterns = settingsDictionary["AutorouteSettings.PatternDefinitions"];
if (oldPatterns.StartsWith("[") && oldPatterns.EndsWith("]"))
newPatterns.Add(oldPatterns.Substring(1, oldPatterns.Length - 2));
}
ContentDefinitionManager.AlterTypeDefinition(partDefinition.contentTypeName, cfg => cfg
.WithPart("AutoroutePart", builder => builder
.WithSetting("AutorouteSettings.PatternDefinitions", "[" + String.Join(",", newPatterns) + "]")
));
}
}
CreateCulturePatterns();
return 5;
}
private void CreateCulturePatterns() {
var autoroutePartDefinitions = ContentDefinitionManager.ListTypeDefinitions()
.Where(type => type.Parts.Any(p => p.PartDefinition.Name == nameof(AutoroutePart)))
.Select(type => new { ContentTypeName = type.Name, AutoroutePart = type.Parts.First(x => x.PartDefinition.Name == nameof(AutoroutePart)) });
foreach (var partDefinition in autoroutePartDefinitions) {
var settingsDictionary = partDefinition.AutoroutePart.Settings;
var settings = settingsDictionary.GetModel<AutorouteSettings>();
if (!settings.Patterns.Any(pattern => string.IsNullOrWhiteSpace(pattern.Culture))) {
var siteCulture = _cultureManager.GetSiteCulture();
List<string> newPatterns = new List<string>();
var siteCulturePatterns = settings.Patterns
.Where(pattern => string.Equals(pattern.Culture, siteCulture, StringComparison.OrdinalIgnoreCase)).ToList();
if (siteCulturePatterns.Any()) {
foreach (RoutePattern pattern in siteCulturePatterns) {
newPatterns.Add($"{{\"Name\":\"{pattern.Name}\",\"Pattern\":\"{pattern.Pattern}\",\"Description\":\"{pattern.Description}\"}}");
}
}
else {
newPatterns.Add("{{\"Name\":\"Title\",\"Pattern\":\"{Content.Slug}\",\"Description\":\"my-title\"}}");
}
if (settingsDictionary.TryGetValue("AutorouteSettings.PatternDefinitions", out var oldPatterns) &&
oldPatterns.StartsWith("[") && oldPatterns.EndsWith("]")) {
newPatterns.Add(oldPatterns.Substring(1, oldPatterns.Length - 2));
}
ContentDefinitionManager.AlterTypeDefinition(partDefinition.ContentTypeName, type => type
.WithPart(nameof(AutoroutePart), builder => builder
.WithSetting("AutorouteSettings.PatternDefinitions", "[" + string.Join(",", newPatterns) + "]")));
}
}
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Orchard.Blogs.Extensions;
@ -98,6 +99,18 @@ namespace Orchard.Blogs.Controllers {
return Redirect(Url.BlogPostEdit(blogPost));
}
public ActionResult CreateWithoutBlog() {
var blogs = _blogService.Get().ToArray();
if (blogs.Count() == 0) {
Services.Notifier.Warning(T("To create a BlogPost you need to create a blog first. You have been redirected to the Blog creation page."));
return RedirectToAction("Create", "BlogAdmin", new { area = "Orchard.Blogs" });
} else {
Services.Notifier.Warning(T("To create a BlogPost you need to choose a blog first. You have been redirected to the Blog selection page."));
return RedirectToAction("List", "BlogAdmin", new { area = "Orchard.Blogs" });
}
}
//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) {

View File

@ -5,13 +5,18 @@ using Orchard.Blogs.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Security;
namespace Orchard.Blogs.Handlers {
public class BlogPostPartHandler : ContentHandler {
private readonly IAuthorizationService _authorizationService;
private readonly IBlogService _blogService;
private readonly IWorkContextAccessor _workContextAccessor;
public BlogPostPartHandler(IBlogService blogService, IBlogPostService blogPostService, RequestContext requestContext) {
public BlogPostPartHandler(IAuthorizationService authorizationService, IBlogService blogService, IBlogPostService blogPostService, RequestContext requestContext, IWorkContextAccessor workContextAccessor) {
_authorizationService = authorizationService;
_blogService = blogService;
_workContextAccessor = workContextAccessor;
OnGetDisplayShape<BlogPostPart>(SetModelProperties);
OnGetEditorShape<BlogPostPart>(SetModelProperties);
@ -45,8 +50,29 @@ namespace Orchard.Blogs.Handlers {
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
var blogPost = context.ContentItem.As<BlogPostPart>();
if (blogPost == null) {
return;
}
int blogId = 0;
// BlogPart can be null if this is a new Blog Post item.
if (blogPost == null || blogPost.BlogPart == null) {
if (blogPost.BlogPart == null) {
var blogs = _blogService.Get().Where(x => _authorizationService.TryCheckAccess(Permissions.MetaListBlogs, _workContextAccessor.GetContext().CurrentUser, x)).ToArray();
if (blogs.Count() == 1) {
var singleBlog = blogs.ElementAt(0);
if (singleBlog != null) blogId = singleBlog.Id;
}
} else {
blogId = blogPost.BlogPart.Id;
}
if (blogId == 0) {
context.Metadata.CreateRouteValues = new RouteValueDictionary {
{"Area", "Orchard.Blogs"},
{"Controller", "BlogPostAdmin"},
{"Action", "CreateWithoutBlog"}
};
return;
}
@ -54,21 +80,21 @@ namespace Orchard.Blogs.Handlers {
{"Area", "Orchard.Blogs"},
{"Controller", "BlogPostAdmin"},
{"Action", "Create"},
{"blogId", blogPost.BlogPart.Id}
{"blogId", blogId}
};
context.Metadata.EditorRouteValues = new RouteValueDictionary {
{"Area", "Orchard.Blogs"},
{"Controller", "BlogPostAdmin"},
{"Action", "Edit"},
{"postId", context.ContentItem.Id},
{"blogId", blogPost.BlogPart.Id}
{"blogId", blogId}
};
context.Metadata.RemoveRouteValues = new RouteValueDictionary {
{"Area", "Orchard.Blogs"},
{"Controller", "BlogPostAdmin"},
{"Action", "Delete"},
{"postId", context.ContentItem.Id},
{"blogId", blogPost.BlogPart.Id}
{"blogId", blogId}
};
}
}

View File

@ -88,6 +88,20 @@ namespace Orchard.Blogs {
},
new MvcRouteHandler())
},
new RouteDescriptor {
Route = new Route(
"Admin/Blogs/Posts/CreateWithoutBlog",
new RouteValueDictionary {
{"area", "Orchard.Blogs"},
{"controller", "BlogPostAdmin"},
{"action", "CreateWithoutBlog"}
},
new RouteValueDictionary (),
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
},
new MvcRouteHandler())
},
new RouteDescriptor {
Route = new Route(
"Admin/Blogs/{blogId}/Posts/{postId}/Edit",

View File

@ -160,6 +160,7 @@ namespace Orchard.ContentPicker.Controllers {
RouteData.Values["Options.SelectedFilter"] = model.Options.SelectedFilter;
RouteData.Values["Options.OrderBy"] = model.Options.OrderBy.ToString();
RouteData.Values["Options.ContentsStatus"] = model.Options.ContentsStatus.ToString();
RouteData.Values["Options.SelectedCulture"] = model.Options.SelectedCulture;
return new ShapeResult(this, Services.New.ContentPicker().Tab(tab));
}

View File

@ -1,12 +1,18 @@
jQuery(function ($) {
Initialize = function () {
$('.button.addSelected').on('click', function () {
var selectedItems = $('.content-picker-itemCheck:checked');
var itemsToAdd = new Array();
$.each(selectedItems, function (index, item) {
var related = $(item).siblings('.content-picker-item').children('.related');
$('.content-picker-itemCheck').each(function () {
var related = $(this).siblings('.content-picker-item').children('.related');
if (window.sessionStorage.getItem(related.data("id")) != null) {
$(this).prop('checked', true);
}
});
$('.content-picker-itemCheck').change(function () {
var related = $(this).siblings('.content-picker-item').children('.related');
if (this.checked) {
var data = {
id: related.data("id"),
displayText: related.data("display-text"),
@ -16,13 +22,27 @@
displayLink: related.data("display-link"),
published: related.data("published")
};
return itemsToAdd.push(data);
});
window.sessionStorage.setItem(related.data("id"), JSON.stringify(data));
} else {
window.sessionStorage.removeItem(related.data("id"));
}
});
$('.button.addSelected').on('click', function () {
var itemsToAdd = new Array();
for (var i = 0; i < sessionStorage.length; i++) {
var data = window.sessionStorage.getItem(sessionStorage.key(i));
itemsToAdd.push(JSON.parse(data));
}
window.sessionStorage.clear();
window.opener.jQuery[query("callback")](itemsToAdd);
window.close();
});
$('.content-picker-SelectAll').on('click', function () {
$('.content-picker-itemCheck').prop('checked', $(this).prop("checked"));
$('.content-picker-itemCheck').change();
});
};

View File

@ -16,7 +16,7 @@
var fieldName = Model.FieldName;
var baseUrl = Url.Content("~/") + WorkContext.Resolve<ShellSettings>().RequestUrlPrefix;
var types = String.Join(",", (IEnumerable<string>)Model.Types ?? Enumerable.Empty<string>());
}
}
<fieldset class="content-picker-field"
data-required="@required.ToString().ToLower()"
@ -50,7 +50,7 @@
<tr>
<td>&nbsp;</td>
<td>
<span data-id="@contentItem.Id" data-fieldid="@idsFieldId" class="content-picker-item">@Html.ItemAdminLink(contentItem) @if (!contentItem.HasPublished()){<text> - </text>@T("Not Published")}</span>
<span data-id="@contentItem.Id" data-fieldid="@idsFieldId" class="content-picker-item">@Html.ItemAdminLink(null, contentItem, new { ReturnUrl = @Request.Url.ToString()}) @if (!contentItem.HasPublished()){<text> - </text>@T("Not Published")}</span>
</td>
<td>
<span data-id="@contentItem.Id" class="content-picker-remove button grey">@T("Remove")</span>

View File

@ -5,7 +5,9 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Descriptors;
using Orchard.Environment.Configuration;
using Orchard.FileSystems.VirtualPath;
using Orchard.Mvc.Routes;
using Orchard.UI.Zones;
namespace Orchard.Layouts.Services {
@ -30,9 +32,9 @@ namespace Orchard.Layouts.Services {
_requestContext = requestContext;
_virtualPathProvider = virtualPathProvider;
_workContextAccessor = workContextAccessor;
}
public abstract UrlPrefix TenantUrlPrefix { get; }
public abstract string DefaultStereotype { get; }
public BuildDisplayContext BuildDisplayContext(IContent content, string displayType, string groupId) {
@ -145,7 +147,12 @@ namespace Orchard.Layouts.Services {
/// Gets the current app-relative path, i.e. ~/my-blog/foo.
/// </summary>
private string GetPath() {
return VirtualPathUtility.AppendTrailingSlash(_virtualPathProvider.ToAppRelative(_requestContext.HttpContext.Request.Path));
var appRelativePath = _virtualPathProvider.ToAppRelative(_requestContext.HttpContext.Request.Path);
// If the tenant has a prefix, we strip the tenant prefix away.
if (TenantUrlPrefix != null)
appRelativePath = TenantUrlPrefix.RemoveLeadingSegments(appRelativePath);
return VirtualPathUtility.AppendTrailingSlash(appRelativePath);
}
}
}

View File

@ -6,24 +6,39 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Descriptors;
using Orchard.Environment.Configuration;
using Orchard.FileSystems.VirtualPath;
using Orchard.Mvc.Routes;
namespace Orchard.Layouts.Services {
public class ContentFieldDisplay : ContentDisplayBase, IContentFieldDisplay {
private readonly IEnumerable<IContentFieldDriver> _contentFieldDrivers;
private readonly ShellSettings _shellSettings;
public ContentFieldDisplay(
IShapeFactory shapeFactory,
Lazy<IShapeTableLocator> shapeTableLocator,
Lazy<IShapeTableLocator> shapeTableLocator,
RequestContext requestContext,
IVirtualPathProvider virtualPathProvider,
IWorkContextAccessor workContextAccessor,
IEnumerable<IContentFieldDriver> contentFieldDrivers)
IWorkContextAccessor workContextAccessor,
ShellSettings shellSettings,
IEnumerable<IContentFieldDriver> contentFieldDrivers)
: base(shapeFactory, shapeTableLocator, requestContext, virtualPathProvider, workContextAccessor) {
_shellSettings = shellSettings;
_contentFieldDrivers = contentFieldDrivers;
}
public override UrlPrefix TenantUrlPrefix {
get {
if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) {
return new UrlPrefix(_shellSettings.RequestUrlPrefix);
}
else {
return null;
}
}
}
public override string DefaultStereotype {
get { return "ContentField"; }
}
@ -63,7 +78,7 @@ namespace Orchard.Layouts.Services {
if (result != null)
result.Apply(context);
}, Logger);
return context.Shape;
}

View File

@ -6,23 +6,38 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Descriptors;
using Orchard.Environment.Configuration;
using Orchard.FileSystems.VirtualPath;
using Orchard.Mvc.Routes;
namespace Orchard.Layouts.Services {
public class ContentPartDisplay : ContentDisplayBase, IContentPartDisplay {
private readonly IEnumerable<IContentPartDriver> _contentPartDrivers;
private readonly ShellSettings _shellSettings;
public ContentPartDisplay(
IShapeFactory shapeFactory,
Lazy<IShapeTableLocator> shapeTableLocator,
RequestContext requestContext,
IVirtualPathProvider virtualPathProvider,
IWorkContextAccessor workContextAccessor,
IWorkContextAccessor workContextAccessor,
ShellSettings shellSettings,
IEnumerable<IContentPartDriver> contentPartDrivers)
: base(shapeFactory, shapeTableLocator, requestContext, virtualPathProvider, workContextAccessor) {
_shellSettings = shellSettings;
_contentPartDrivers = contentPartDrivers;
}
public override UrlPrefix TenantUrlPrefix {
get {
if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) {
return new UrlPrefix(_shellSettings.RequestUrlPrefix);
}
else {
return null;
}
}
}
public override string DefaultStereotype {
get { return "ContentPart"; }

View File

@ -1,4 +1,6 @@
@{
@using System.Globalization
@{
var currentCulture = WorkContext.CurrentCulture;
var supportedCultures = (IList<string>)Model.SupportedCultures;
}
@ -6,15 +8,20 @@
<div id="culture-selection">
<ul>
@foreach (var supportedCulture in supportedCultures) {
var url = Url.Action("ChangeCulture", "AdminCultureSelector", new { area = "Orchard.Localization", culture = supportedCulture, returnUrl = Html.ViewContext.HttpContext.Request.RawUrl });
var culture = CultureInfo.GetCultureInfo(supportedCulture);
<li>
@if (supportedCulture.Equals(currentCulture)) {
<a href="@url">@T("{0} (current)", supportedCulture)</a>
} else {
<a href="@url">@supportedCulture</a>
}
</li>
if (culture is object)
{
var url = Url.Action("ChangeCulture", "AdminCultureSelector", new { area = "Orchard.Localization", culture = supportedCulture, returnUrl = Html.ViewContext.HttpContext.Request.RawUrl });
<li>
@if (supportedCulture.Equals(currentCulture)) {
<a href="@url">@T("{0} (current)", culture.DisplayName)</a>
} else {
<a href="@url">@culture.DisplayName</a>
}
</li>
}
}
</ul>
</div>

View File

@ -3,6 +3,7 @@
@using Orchard.ContentManagement
@using Orchard.ContentManagement.Aspects
@using Orchard.Localization.Services
@{
var localizableAspects = Enumerable.Empty<ILocalizableAspect>();
var homePage = WorkContext.Resolve<IHomeAliasService>().GetHomePage();
@ -12,26 +13,24 @@
localizableAspects = localizationService.GetLocalizations(homePage).Concat(new[] { homePage.As<ILocalizableAspect>() });
}
}
@if (localizableAspects.Any()) {
<div>
<ul>
@foreach (var localization in localizableAspects) {
<div>
<ul>
@foreach (var localization in localizableAspects.Where(localization => !string.IsNullOrEmpty(localization.Culture))) {
var culture = CultureInfo.GetCultureInfo(localization.Culture);
if (localization.Culture == null) {
continue;
if (culture is object) {
<li>
@if (localization.Culture.Equals(WorkContext.CurrentCulture, StringComparison.InvariantCultureIgnoreCase)) {
<a href="@Url.ItemDisplayUrl(localization)">@T("{0} (current)", culture.DisplayName)</a>
}
else {
<a href="@Url.ItemDisplayUrl(localization)">@culture.DisplayName</a>
}
</li>
}
}
var culture = CultureInfo.GetCultureInfo(localization.Culture);
<li>
@if (localization.Culture.Equals(WorkContext.CurrentCulture, StringComparison.InvariantCultureIgnoreCase)) {
<a href="@Url.ItemDisplayUrl(localization)">@T("{0} (current)", culture.DisplayName)</a>
}
else {
<a href="@Url.ItemDisplayUrl(localization)">@T("{0}", culture.DisplayName)</a>
}
</li>
}
</ul>
</div>
</ul>
</div>
}

View File

@ -1,15 +1,15 @@
var enhanceViewModel = function(viewModel) {
var enhanceViewModel = function (viewModel) {
// extension point for other modules to alter the view model
};
var baseViewModel = function() {
var baseViewModel = function () {
};
$(function () {
(function (settings) {
function attachFolderTitleDropEvent (elements) {
function attachFolderTitleDropEvent(elements) {
elements.droppable({
accept: function () {
var targetId = $(this).data('term-id');
@ -47,7 +47,7 @@ $(function () {
folderPath: folderPath,
mediaItemIds: ids,
__RequestVerificationToken: settings.antiForgeryToken
},
}
}).done(function (result) {
if (result) {
if (viewModel.displayed()) {
@ -67,7 +67,7 @@ $(function () {
});
}
});
};
}
var listWidth = $('#media-library-main-list').width();
var listHeight = $('#media-library-main-list').height();
@ -105,7 +105,7 @@ $(function () {
self.selected = ko.observable();
self.status = ko.observable('');
self.summary = ko.observable('');
self.cssClass = ko.computed(function() {
self.cssClass = ko.computed(function () {
var css = '';
if (self.selected()) {
css += ' selected';
@ -118,14 +118,14 @@ $(function () {
return css;
});
self.mediaInfos = ko.computed(function () {
self.publicationStatus = ko.computed(function () {
var pubStatus = self.data.published ? "" : draftText;
var localization = (self.data.localization != "" ? "(" + self.data.localization + ")" : "");
return pubStatus + " " + localization;
});
// operations
self.setData = function(value) {
self.setData = function (value) {
self.data = value;
};
}
@ -142,6 +142,11 @@ $(function () {
self.focus = ko.observable();
self.results = ko.observableArray();
self.displayed = ko.observable();
self.isEveryItemSelected = ko.computed({
read: function () {
return self.selection().length === self.results().length;
}
});
self.mediaItemsCount = 0;
self.orderMedia = ko.observableArray(['created']);
self.mediaType = ko.observableArray([]);
@ -150,7 +155,7 @@ $(function () {
self.mediaFoldersRequestCount = ko.observable(0);
self.mediaFoldersPendingRequest = ko.computed({
read: function () {
return (self.mediaFoldersRequestCount() > 0);
return self.mediaFoldersRequestCount() > 0;
},
write: function (value) {
if (value === true) {
@ -164,7 +169,7 @@ $(function () {
self.mediaPendingRequest = ko.observable(false);
self.pendingRequest = ko.computed({
read: function () {
return (self.mediaFoldersPendingRequest() || self.mediaPendingRequest());
return self.mediaFoldersPendingRequest() || self.mediaPendingRequest();
},
write: function (value) {
self.mediaPendingRequest(value);
@ -173,7 +178,7 @@ $(function () {
self.getMediaItems = function (count, append) {
var folderPath = self.displayed() || '';
if (self.mediaPendingRequest()) {
return;
}
@ -189,13 +194,12 @@ $(function () {
self.pendingRequest(true);
var url = self.loadMediaItemsUrl(folderPath, self.results().length, count, self.orderMedia(), self.mediaType());
console.log(url);
$.ajax({
type: "GET",
url: url,
cache: false
}).done(function(data) {
}).done(function (data) {
var mediaItems = data.mediaItems;
var mediaItemsFolderPath = data.folderPath;
@ -216,35 +220,60 @@ $(function () {
}
}
}
}).fail(function(data) {
self.updateSelectAllText();
}).fail(function (data) {
console.error(data);
}).always(function() {
}).always(function () {
self.pendingRequest(false);
});
};
self.clearSelection = function() {
self.updateSelectAllText = function () {
var element = $("#select-all-button");
element.html(self.isEveryItemSelected() ? element.data("select-none-text") : element.data("select-all-text"));
};
self.updateAllSelection = function () {
if (self.isEveryItemSelected()) {
self.clearSelection();
}
else {
self.selectAll();
}
self.updateSelectAllText();
};
self.selectAll = function () {
self.results().forEach(function (item) {
viewModel.toggleSelect(item, true);
});
};
self.clearSelection = function () {
this.focus(null);
// unselect previous elements
self.selection().forEach(function(item) {
self.selection().forEach(function (item) {
item.selected(false);
});
self.selection([]);
};
self.focus.subscribe(function(oldValue) {
self.focus.subscribe(function (oldValue) {
if (oldValue) {
oldValue.hasFocus(false);
}
}, this, "beforeChange");
self.afterRenderMediaFolderTemplate = function(elements, model) {
self.afterRenderMediaFolderTemplate = function (elements, model) {
var childTitles = $(elements).find(".media-library-folder-title");
attachFolderTitleDropEvent(childTitles);
};
self.focus.subscribe(function(newValue) {
self.focus.subscribe(function (newValue) {
if (newValue) {
newValue.hasFocus(true);
@ -257,21 +286,21 @@ $(function () {
type: "GET",
url: url,
cache: false
}).done(function(data) {
}).done(function (data) {
newValue.summary(data);
});
}
}
});
self.displayFolder = function(folderPath) {
self.displayFolder = function (folderPath) {
self.results([]);
self.displayed(folderPath);
self.loadMediaItemsUrl = function (f, skip, count, order, mediaType) {
return settings.mediaItemsActionUrl + '?folderPath=' + encodeURIComponent(f) + '&skip=' + skip + '&count=' + count + '&order=' + order + '&mediaType=' + mediaType;
};
self.getMediaItems(pageCount);
};
@ -280,22 +309,22 @@ $(function () {
self.displayFolder(folderPath);
};
self.selectRecent = function() {
self.selectRecent = function () {
History.pushState({ action: 'selectRecent' }, '', '?recent');
self.loadMediaItemsUrl = function (folderPath, skip, count, order, mediaType) {
return settings.recentMediaItemsActionUrl + '?skip=' + skip + '&count=' + count + '&order=' + order + '&mediaType=' + mediaType;
};
self.results([]);
self.displayed(null);
self.getMediaItems(pageCount);
};
self.toggleSelect = function(searchResult, force) {
self.toggleSelect = function (searchResult, force) {
var index = $.inArray(searchResult, self.selection());
if (index == -1 || force) {
self.selection.remove(function(item) { return item.data.id == searchResult.data.id; });
self.selection.remove(function (item) { return item.data.id == searchResult.data.id; });
self.selection.push(searchResult);
searchResult.selected(true);
} else {
@ -306,7 +335,7 @@ $(function () {
this.focus(searchResult);
};
self.select = function(searchResult) {
self.select = function (searchResult) {
var index = $.inArray(searchResult, self.selection());
if (index == -1) {
self.clearSelection();
@ -317,14 +346,14 @@ $(function () {
this.focus(searchResult);
};
self.scrolled = function(data, event) {
self.scrolled = function (data, event) {
var elem = event.target;
if (elem.scrollTop > (elem.scrollHeight - elem.offsetHeight - 300)) {
self.getMediaItems(pageCount, true);
}
};
self.importMedia = function() {
self.importMedia = function () {
var url = settings.importActionUrl + '?folderPath=' + encodeURIComponent(self.displayed());
window.location = url;
};
@ -339,7 +368,8 @@ $(function () {
viewModel.selection().forEach(function (item) { ids.push(item.data.id); });
var actionurl = url + '?folderPath=' + encodeURIComponent(folder) + "&replaceId=" + encodeURIComponent(ids[0]);
window.location = actionurl;
}
};
var selectFolderOrRecent = function () {
if (self.displayed()) {
self.selectFolder(self.displayed());
@ -368,13 +398,13 @@ $(function () {
self.isExpanded = ko.observable(false);
self.isSelected = ko.computed(function() {
self.isSelected = ko.computed(function () {
return (self.mediaIndexViewModel.displayed() == self.folderPath());
});
self.fetchChildren = function (deepestChildPath) {
self.childFoldersFetchStatus = 1;
var getChildFolderListUrl = function (f) {
return settings.childFolderListingActionUrl + '?folderPath=' + encodeURIComponent(f);
};
@ -450,7 +480,7 @@ $(function () {
});
enhanceViewModel(viewModel);
ko.applyBindings(viewModel);
if (settings.hasFolderPath && settings.folderPath != settings.rootFolderPath) {
@ -478,7 +508,7 @@ $(function () {
History.pushState({ action: 'selectRecent' }, '', '?recent');
}
window.onpopstate = function(event) {
window.onpopstate = function (event) {
if (event && event.state && event.state.action == 'displayFolder') {
viewModel.displayFolder(event.state.folder);
}
@ -488,7 +518,7 @@ $(function () {
}
};
$("#media-library-main-list").on("mousedown", "li", function(e) {
$("#media-library-main-list").on("mousedown", "li", function (e) {
// only for left click
if (e.which != 1) {
return;
@ -500,46 +530,49 @@ $(function () {
} else {
viewModel.select(searchResult);
}
}).on("contextmenu", "li", function() {
}).on("contextmenu", "li", function () {
var searchResult = ko.dataFor(this);
viewModel.toggleSelect(searchResult);
return false;
});
var pickAndClose = function () {
if (parent.$.colorbox) {
var selectedData = [];
for (var i = 0; i < viewModel.selection().length; i++) {
var selection = viewModel.selection()[i];
selectedData.push(selection.data);
}
parent.$.colorbox.selectedData = selectedData;
parent.$.colorbox.close();
};
}
if (parent.$.colorbox) {
var selectedData = [];
for (var i = 0; i < viewModel.selection().length; i++) {
var selection = viewModel.selection()[i];
selectedData.push(selection.data);
}
parent.$.colorbox.selectedData = selectedData;
parent.$.colorbox.close();
}
};
$("#media-library-main-selection-select > .button-select").on('click', function () {
pickAndClose();
pickAndClose();
});
$("#select-all-button").on('click', function () {
viewModel.updateAllSelection();
});
$("#media-library-main-list").on('dblclick', function () {
pickAndClose();
pickAndClose();
});
$("#media-library-main-selection-select > .button-cancel").on('click', function() {
$("#media-library-main-selection-select > .button-cancel").on('click', function () {
if (parent.$.colorbox) {
parent.$.colorbox.selectedData = null;
parent.$.colorbox.close();
}
;
});
$("#media-library-main-list").on("mouseover", ".media-thumbnail", function() {
$("#media-library-main-list").on("mouseover", ".media-thumbnail", function () {
if (!$(this).hasClass("ui-draggable")) {
$(this).draggable({
revert: 'invalid',
//containment: 'li',
helper: function(event) {
helper: function (event) {
var clone = $(event.currentTarget).clone().removeAttr('id');
clone.removeClass('selected');
clone.addClass('dragged-selection');
@ -554,7 +587,7 @@ $(function () {
cursor: 'move',
distance: 10,
appendTo: 'body',
create: function() {
create: function () {
// position the handler a little left to the center to let the number of selected items to appear
$(this).draggable("option", "cursorAt", { left: $(this).width() / 2 - 20, top: $(this).height() / 2 });
}
@ -562,13 +595,13 @@ $(function () {
}
});
$('#delete-selection-button').click(function() {
$('#delete-selection-button').click(function () {
if (!confirm(settings.deleteConfirmationMessage)) {
return false;
}
var ids = [];
viewModel.selection().forEach(function(item) { ids.push(item.data.id); });
viewModel.selection().forEach(function (item) { ids.push(item.data.id); });
var url = settings.deleteActionUrl;
$.ajax({
@ -580,9 +613,9 @@ $(function () {
mediaItemIds: ids,
__RequestVerificationToken: settings.antiForgeryToken
}
}).done(function(result) {
}).done(function (result) {
if (result) {
viewModel.results.remove(function(item) {
viewModel.results.remove(function (item) {
return ids.indexOf(item.data.id) != -1;
});
@ -632,4 +665,4 @@ $(function () {
});
})(window.mediaLibrarySettings);
})
});

View File

@ -95,7 +95,8 @@ namespace Orchard.MediaLibrary.Services {
if (!String.IsNullOrEmpty(folderPath)) {
if (recursive) {
query = query.Join<MediaPartRecord>().Where(m => m.FolderPath.StartsWith(folderPath));
var subfolderSearch = folderPath.EndsWith(Path.DirectorySeparatorChar.ToString()) ? folderPath : folderPath + Path.DirectorySeparatorChar;
query = query.Join<MediaPartRecord>().Where(m => (m.FolderPath == folderPath || m.FolderPath.StartsWith(subfolderSearch)));
}
else {
query = query.Join<MediaPartRecord>().Where(m => m.FolderPath == folderPath);

View File

@ -22,6 +22,11 @@
<a href="#" data-bind="attr: { href: '@HttpUtility.JavaScriptStringEncode(Url.Action("Create", "Folder", new { area = "Orchard.MediaLibrary"}))?folderPath=' + encodeURIComponent(displayed() ? displayed() : '') }" class="button" id="button-create-folder">@T("Create Folder")</a>
@Display(Model.CustomActionsShapes)
<button class="button" id="select-all-button"
data-select-all-text="@T("Select All")" data-select-none-text="@T("Select None")"
data-bind="visible: results().length > 0">
@T("Select All")
</button>
</div>
<div id="media-library-main">
<div id="media-library-main-navigation">
@ -43,7 +48,7 @@
</div>
<div class="media-library-main-list-overlay">
<p class="title" data-bind="text: data.title, attr: { title: data.title }"></p>
<p class="publication-status" data-bind="text: mediaInfos"></p>
<p class="publication-status" data-bind="text: publicationStatus"></p>
</div>
</li>
</ul>

View File

@ -47,7 +47,7 @@
@Display(BuildDisplay(contentItem, "Thumbnail"))
<div class="overlay">
<h3>@Html.ItemDisplayText(contentItem)</h3>
<p class="publication-status" data-bind="text: mediaInfos">
<p class="publication-status" data-bind="text: publicationStatus">
@(contentItem.IsPublished() ? "" : T("Draft").Text)
@{
var localizationPart = contentItem.As<LocalizationPart>();

View File

@ -44,7 +44,7 @@ namespace Orchard.Packaging.Services {
}
public Localizer T { get; set; }
public Logging.ILogger Logger { get; set; }
public Logging.ILogger Logger { get; set; }
public PackageInfo Install(string packageId, string version, string location, string applicationPath) {
// instantiates the appropriate package repository
@ -54,7 +54,9 @@ namespace Orchard.Packaging.Services {
var packageVersion = String.IsNullOrEmpty(version) ? null : new Version(version);
var package = packageRepository.FindPackage(packageId, packageVersion);
if (package == null) {
throw new ArgumentException(T("The specified package could not be found, id:{0} version:{1}", packageId, String.IsNullOrEmpty(version) ? T("No version").Text : version).Text);
var message = T("The specified package could not be found: ID: {0}, version: {1}.",
packageId, string.IsNullOrEmpty(version) ? T("No version").Text : version);
throw new OrchardException(message);
}
return InstallPackage(package, packageRepository, location, applicationPath);
@ -92,8 +94,8 @@ namespace Orchard.Packaging.Services {
// check the new package is compatible with current Orchard version
var descriptor = package.GetExtensionDescriptor(packageInfo.ExtensionType);
if(descriptor != null) {
if(new FlatPositionComparer().Compare(descriptor.OrchardVersion, typeof(ContentItem).Assembly.GetName().Version.ToString()) >= 0) {
if (descriptor != null) {
if (new FlatPositionComparer().Compare(descriptor.OrchardVersion, typeof(ContentItem).Assembly.GetName().Version.ToString()) >= 0) {
if (previousInstalled) {
// restore the previous version
RestoreExtensionFolder(package.ExtensionFolder(), package.ExtensionId());
@ -105,7 +107,7 @@ namespace Orchard.Packaging.Services {
Logger.Error(String.Format("The package is compatible with version {0} and above. Please update Orchard or install another version of this package.", descriptor.OrchardVersion));
throw new OrchardException(T("The package is compatible with version {0} and above. Please update Orchard or install another version of this package.", descriptor.OrchardVersion));
}
}
}
return packageInfo;
@ -134,8 +136,8 @@ namespace Orchard.Packaging.Services {
var packageManager = new NuGetPackageManager(
packageRepository,
new DefaultPackagePathResolver(sourceLocation),
new PhysicalFileSystem(installedPackagesPath) {Logger = logger}
) {Logger = logger};
new PhysicalFileSystem(installedPackagesPath) { Logger = logger }
) { Logger = logger };
packageManager.InstallPackage(package, true);
installed = true;
@ -181,7 +183,8 @@ namespace Orchard.Packaging.Services {
if (packageId.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme))) {
extensionFullPath = _virtualPathProvider.MapPath("~/Themes/" + packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme).Length));
} else if (packageId.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module))) {
}
else if (packageId.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module))) {
extensionFullPath = _virtualPathProvider.MapPath("~/Modules/" + packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module).Length));
}
@ -201,13 +204,13 @@ namespace Orchard.Packaging.Services {
var sourcePackageRepository = new LocalPackageRepository(installedPackagesPath);
try {
var project = new FileBasedProjectSystem(applicationPath) {Logger = logger};
var project = new FileBasedProjectSystem(applicationPath) { Logger = logger };
var projectManager = new ProjectManager(
sourcePackageRepository,
new DefaultPackagePathResolver(installedPackagesPath),
project,
new ExtensionReferenceRepository(project, sourcePackageRepository, _extensionManager)
) {Logger = logger};
) { Logger = logger };
// add the package to the project
projectManager.RemovePackageReference(packageId);
@ -220,8 +223,8 @@ namespace Orchard.Packaging.Services {
var packageManager = new NuGetPackageManager(
sourcePackageRepository,
new DefaultPackagePathResolver(applicationPath),
new PhysicalFileSystem(installedPackagesPath) {Logger = logger}
) {Logger = logger};
new PhysicalFileSystem(installedPackagesPath) { Logger = logger }
) { Logger = logger };
packageManager.UninstallPackage(packageId);
}
@ -314,7 +317,7 @@ namespace Orchard.Packaging.Services {
Uninstall(package.Id, _virtualPathProvider.MapPath("~\\"));
_notifier.Success(T("Successfully un-installed local package {0}", package.ExtensionId()));
}
catch {}
catch { }
}
}
}

View File

@ -1,9 +1,7 @@
using System;
using System.IO;
using System.Linq;
using NuGet;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Folders;
using Orchard.Environment.Extensions.Models;
using Orchard.Environment.Features;
using Orchard.Environment.State;

View File

@ -49,6 +49,10 @@ namespace Orchard.Projections.FilterEditors.Forms {
f._Operator.Add(new SelectListItem { Value = Convert.ToString(StringOperator.Ends), Text = T("Ends with").Text });
f._Operator.Add(new SelectListItem { Value = Convert.ToString(StringOperator.NotEnds), Text = T("Does not end with").Text });
f._Operator.Add(new SelectListItem { Value = Convert.ToString(StringOperator.NotContains), Text = T("Does not contain").Text });
f._Operator.Add(new SelectListItem {
Value = Convert.ToString(StringOperator.ContainsAnyIfProvided),
Text = T("Contains any word (if any is provided)").Text
});
return f;
};
@ -88,6 +92,14 @@ namespace Orchard.Projections.FilterEditors.Forms {
return y => y.Not(x => x.Like(property, Convert.ToString(value), HqlMatchMode.End));
case StringOperator.NotContains:
return y => y.Not(x => x.Like(property, Convert.ToString(value), HqlMatchMode.Anywhere));
case StringOperator.ContainsAnyIfProvided:
if (string.IsNullOrWhiteSpace((string)value))
return x => x.IsNotEmpty("Id"); // basically, return every possible ContentItem
var values3 = Convert.ToString(value)
.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var predicates3 = values3.Skip(1)
.Select<string, Action<IHqlExpressionFactory>>(x => y => y.Like(property, x, HqlMatchMode.Anywhere)).ToArray();
return x => x.Disjunction(y => y.Like(property, values3[0], HqlMatchMode.Anywhere), predicates3);
default:
throw new ArgumentOutOfRangeException();
}
@ -118,6 +130,11 @@ namespace Orchard.Projections.FilterEditors.Forms {
return T("{0} does not end with '{1}'", fieldName, value);
case StringOperator.NotContains:
return T("{0} does not contain '{1}'", fieldName, value);
case StringOperator.ContainsAnyIfProvided:
return T("{0} contains any of '{1}' (or '{1}' is empty)",
fieldName,
new LocalizedString(string.Join("', '",
value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))));
default:
throw new ArgumentOutOfRangeException();
}
@ -135,5 +152,6 @@ namespace Orchard.Projections.FilterEditors.Forms {
Ends,
NotEnds,
NotContains,
ContainsAnyIfProvided
}
}

View File

@ -1,4 +1,5 @@
@using System.Globalization
@{
var currentCulture = WorkContext.CurrentCulture;
var supportedCultures = (IList<string>)Model.SupportedCultures;
@ -8,22 +9,25 @@
<select>
@foreach (var supportedCulture in supportedCultures) {
var cultureInfo = CultureInfo.GetCultureInfo(supportedCulture);
var url = Url.Action("ChangeCulture", "AdminCultureSelector", new { area = "Orchard.Localization", culture = supportedCulture, returnUrl = Html.ViewContext.HttpContext.Request.RawUrl });
<option @if (supportedCulture.Equals(currentCulture)) { <text> selected="selected" </text> } value="@url">
@cultureInfo.DisplayName&#x200E;
</option>
if (cultureInfo is object) {
var url = Url.Action("ChangeCulture", "AdminCultureSelector", new { area = "Orchard.Localization", culture = supportedCulture, returnUrl = Html.ViewContext.HttpContext.Request.RawUrl });
var selected = supportedCulture.Equals(currentCulture) ? "selected" : "";
<option @selected value="@url">@cultureInfo.DisplayName</option>
}
}
</select>
</div>
@using (Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
(function ($) {
$("#culture-selection").change(function (e) {
window.location = $("#culture-selection > select > option:selected")[0].value;
});
})(jQuery);
//]]>
</script>
<script type="text/javascript">
//<![CDATA[
(function ($) {
$("#culture-selection").change(function (e) {
window.location = $("#culture-selection > select > option:selected")[0].value;
});
})(jQuery);
//]]>
</script>
}

View File

@ -24,4 +24,12 @@ namespace Orchard.ContentManagement {
public readonly IList<GroupInfo> DisplayGroupInfo = new List<GroupInfo>();
public readonly IList<GroupInfo> EditorGroupInfo = new List<GroupInfo>();
}
public enum ContentItemRoute {
Admin,
Create,
Editor,
Remove,
Display
}
}

View File

@ -5,8 +5,10 @@ using System.Web.Routing;
using Orchard.ContentManagement.Handlers;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Descriptors;
using Orchard.Environment.Configuration;
using Orchard.FileSystems.VirtualPath;
using Orchard.Logging;
using Orchard.Mvc.Routes;
using Orchard.UI.Zones;
namespace Orchard.ContentManagement {
@ -18,6 +20,8 @@ namespace Orchard.ContentManagement {
private readonly RequestContext _requestContext;
private readonly IVirtualPathProvider _virtualPathProvider;
private readonly IWorkContextAccessor _workContextAccessor;
private readonly ShellSettings _shellSettings;
private readonly UrlPrefix _urlPrefix;
public DefaultContentDisplay(
Lazy<IEnumerable<IContentHandler>> handlers,
@ -25,15 +29,19 @@ namespace Orchard.ContentManagement {
Lazy<IShapeTableLocator> shapeTableLocator,
RequestContext requestContext,
IVirtualPathProvider virtualPathProvider,
IWorkContextAccessor workContextAccessor) {
IWorkContextAccessor workContextAccessor,
ShellSettings shellSettings) {
_handlers = handlers;
_shapeFactory = shapeFactory;
_shapeTableLocator = shapeTableLocator;
_requestContext = requestContext;
_virtualPathProvider = virtualPathProvider;
_workContextAccessor = workContextAccessor;
_shellSettings = shellSettings;
if (!string.IsNullOrEmpty(_shellSettings.RequestUrlPrefix))
_urlPrefix = new UrlPrefix(_shellSettings.RequestUrlPrefix);
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
@ -158,7 +166,12 @@ namespace Orchard.ContentManagement {
/// Gets the current app-relative path, i.e. ~/my-blog/foo.
/// </summary>
private string GetPath() {
return VirtualPathUtility.AppendTrailingSlash(_virtualPathProvider.ToAppRelative(_requestContext.HttpContext.Request.Path));
var appRelativePath = _virtualPathProvider.ToAppRelative(_requestContext.HttpContext.Request.Path);
// If the tenant has a prefix, we strip the tenant prefix away.
if (_urlPrefix != null)
appRelativePath = _urlPrefix.RemoveLeadingSegments(appRelativePath);
return VirtualPathUtility.AppendTrailingSlash(appRelativePath);
}
}
}

View File

@ -1,29 +0,0 @@
using System.Web.Routing;
using System.Web.Mvc;
namespace Orchard.Mvc.Extensions {
public static class RouteExtension{
public static string GetAreaName(this RouteBase route){
var routeWithArea = route as IRouteWithArea;
if (routeWithArea != null) {
return routeWithArea.Area;
}
var castRoute = route as Route;
if (castRoute != null && castRoute.DataTokens != null) {
return castRoute.DataTokens["area"] as string;
}
return null;
}
public static string GetAreaName(this RouteData routeData){
object area;
if (routeData.DataTokens.TryGetValue("area", out area)) {
return area as string;
}
return GetAreaName(routeData.Route);
}
}
}

View File

@ -0,0 +1,25 @@
using System.Web.Mvc;
using System.Web.Routing;
namespace Orchard.Mvc.Extensions {
public static class RouteExtensions {
public static string GetAreaName(this RouteBase route) {
if (route is IRouteWithArea routeWithArea) {
return routeWithArea.Area;
}
if (route is Route castRoute && castRoute.DataTokens != null) {
return castRoute.DataTokens["area"] as string;
}
return null;
}
public static string GetAreaName(this RouteData routeData) =>
routeData.DataTokens.TryGetValue("area", out object area) ?
area as string : GetAreaName(routeData.Route);
public static string ToRouteString(this RouteValueDictionary route) =>
string.Join("/", route["Area"], route["Controller"], route["Action"]);
}
}

View File

@ -401,7 +401,7 @@
<Compile Include="Mvc\DataAnnotations\LocalizedRangeAttribute.cs" />
<Compile Include="Mvc\DataAnnotations\LocalizedModelValidatorProvider.cs" />
<Compile Include="Mvc\DataAnnotations\LocalizedRequiredAttribute.cs" />
<Compile Include="Mvc\Extensions\RouteExtension.cs" />
<Compile Include="Mvc\Extensions\RouteExtensions.cs" />
<Compile Include="Mvc\Extensions\HttpContextBaseExtensions.cs" />
<Compile Include="Mvc\FormValueRequiredAttribute.cs" />
<Compile Include="Mvc\HttpContextAccessor.cs" />

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Orchard.Security.Permissions {
public class Permission {
@ -7,10 +8,12 @@ namespace Orchard.Security.Permissions {
public string Category { get; set; }
public IEnumerable<Permission> ImpliedBy { get; set; }
public bool RequiresOwnership { get; set; }
public static Permission Named(string name) {
return new Permission { Name = name };
}
[Obsolete("This property is not used anywhere, so it shouldn't be referenced.")]
public bool RequiresOwnership { get; set; }
}
}