mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Merge branch '1.9.x' into dev
Conflicts: src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml src/Orchard.Web/Modules/Orchard.Layouts/Assets/JavaScript/Models/Element.js src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.js src/Orchard.Web/Modules/Orchard.Layouts/Scripts/LayoutEditor.min.js src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.js src/Orchard.Web/Modules/Orchard.Layouts/Scripts/Models.min.js src/Orchard.Web/Modules/Orchard.Layouts/Views/LayoutEditor.Template.Toolbox.cshtml src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs src/Orchard.Web/Modules/Orchard.Search/Drivers/SearchSettingsPartDriver.cs src/Orchard.Web/Modules/Orchard.Search/ViewModels/SearchSettingsIndexViewModel.cs src/Orchard.Web/Modules/Orchard.Search/Views/EditorTemplates/Parts/Search.SiteSettings.cshtml src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs src/Orchard/Orchard.Framework.csproj
This commit is contained in:
commit
80c600fa02
@ -264,9 +264,6 @@ namespace Orchard.Tests.Modules.DesignerTools.Services
|
||||
new JProperty("name", "TestingPart"),
|
||||
new JProperty("value", "ContentPart"),
|
||||
new JProperty("children", new JArray(
|
||||
new JObject(
|
||||
new JProperty("name", "Zones"),
|
||||
new JProperty("value", "ZoneCollection")),
|
||||
new JObject(
|
||||
new JProperty("name", "Id"),
|
||||
new JProperty("value", "0")),
|
||||
@ -327,9 +324,6 @@ namespace Orchard.Tests.Modules.DesignerTools.Services
|
||||
new JProperty("name", "TestingPart"),
|
||||
new JProperty("value", "ContentPart"),
|
||||
new JProperty("children", new JArray(
|
||||
new JObject(
|
||||
new JProperty("name", "Zones"),
|
||||
new JProperty("value", "ZoneCollection")),
|
||||
new JObject(
|
||||
new JProperty("name", "Id"),
|
||||
new JProperty("value", "0")),
|
||||
|
@ -512,7 +512,7 @@ Features:
|
||||
Dependencies: Beta
|
||||
");
|
||||
|
||||
moduleExtensionFolder.Manifests.Add("Classic", @"
|
||||
themeExtensionFolder.Manifests.Add("Classic", @"
|
||||
Name: Classic
|
||||
Version: 1.0.3
|
||||
OrchardVersion: 1
|
||||
|
@ -8,7 +8,7 @@
|
||||
<autofac defaultAssembly="Orchard.Framework">
|
||||
|
||||
<!--
|
||||
To create tenant specific configurations, copy this file to ~/Congig/Sites.{tenant}.config
|
||||
To create tenant specific configurations, copy this file to ~/Config/Sites.{tenant}.config
|
||||
where {tenant} is the technical name of the targetted tenant
|
||||
|
||||
Allowed scopes: per-dependency, single-instance or per-lifetime-scope
|
||||
@ -47,4 +47,4 @@
|
||||
</components>
|
||||
</autofac>
|
||||
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
@ -52,7 +52,7 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
if (updater != null) {
|
||||
var oldContainerId = model.ContainerId;
|
||||
updater.TryUpdateModel(model, "Containable", null, new[] { "ShowContainerPicker", "ShowPositionEditor" });
|
||||
if (oldContainerId != model.ContainerId) {
|
||||
if (oldContainerId != model.ContainerId && settings.ShowContainerPicker) {
|
||||
if (commonPart != null) {
|
||||
var containerItem = _contentManager.Get(model.ContainerId, VersionOptions.Latest);
|
||||
commonPart.Container = containerItem;
|
||||
@ -61,20 +61,23 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
part.Position = model.Position;
|
||||
}
|
||||
|
||||
var containers = _contentManager
|
||||
.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest)
|
||||
.List()
|
||||
.Where(container => container.ItemContentTypes.Any(type => type.Name == part.TypeDefinition.Name));
|
||||
if (settings.ShowContainerPicker) {
|
||||
var containers = _contentManager
|
||||
.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest)
|
||||
.List()
|
||||
.Where(container => container.ItemContentTypes.Any(type => type.Name == part.TypeDefinition.Name));
|
||||
|
||||
var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
|
||||
.Concat(containers.Select(x => new SelectListItem {
|
||||
Value = Convert.ToString(x.Id),
|
||||
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + _contentManager.GetItemMetadata(x.ContentItem).DisplayText,
|
||||
Selected = x.Id == model.ContainerId,
|
||||
}))
|
||||
.ToList();
|
||||
var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
|
||||
.Concat(containers.Select(x => new SelectListItem {
|
||||
Value = Convert.ToString(x.Id),
|
||||
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + _contentManager.GetItemMetadata(x.ContentItem).DisplayText,
|
||||
Selected = x.Id == model.ContainerId,
|
||||
}))
|
||||
.ToList();
|
||||
|
||||
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);
|
||||
}
|
||||
|
||||
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);
|
||||
model.Position = part.Position;
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Containable", Model: model, Prefix: "Containable");
|
||||
|
@ -88,6 +88,10 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
|
||||
protected override DriverResult Editor(ContainerPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_Container_Edit", () => {
|
||||
if(!part.ContainerSettings.DisplayContainerEditor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var containables = !part.ContainerSettings.RestrictItemContentTypes ? _containerService.GetContainableTypes().ToList() : new List<ContentTypeDefinition>(0);
|
||||
var model = new ContainerViewModel {
|
||||
AdminMenuPosition = part.AdminMenuPosition,
|
||||
|
@ -48,6 +48,10 @@ namespace Orchard.Core.Containers.Settings {
|
||||
}
|
||||
|
||||
public class ContainerTypePartSettings {
|
||||
public ContainerTypePartSettings() {
|
||||
DisplayContainerEditor = true;
|
||||
}
|
||||
|
||||
public bool? ItemsShownDefault { get; set; }
|
||||
public int? PageSizeDefault { get; set; }
|
||||
public bool? PaginatedDefault { get; set; }
|
||||
@ -55,6 +59,7 @@ namespace Orchard.Core.Containers.Settings {
|
||||
public bool RestrictItemContentTypes { get; set; }
|
||||
public bool? EnablePositioning { get; set; }
|
||||
public string AdminListViewName { get; set; }
|
||||
public bool DisplayContainerEditor { get; set; }
|
||||
}
|
||||
|
||||
public class ContainerSettingsHooks : ContentDefinitionEditorEventsBase {
|
||||
@ -93,7 +98,8 @@ namespace Orchard.Core.Containers.Settings {
|
||||
EnablePositioning = model.EnablePositioning,
|
||||
AdminListViewName = model.AdminListViewName,
|
||||
AvailableItemContentTypes = _containerService.GetContainableTypes().ToList(),
|
||||
ListViewProviders = _listViewService.Providers.ToList()
|
||||
ListViewProviders = _listViewService.Providers.ToList(),
|
||||
DisplayContainerEditor = model.DisplayContainerEditor
|
||||
};
|
||||
|
||||
yield return DefinitionTemplate(viewModel);
|
||||
@ -122,6 +128,7 @@ namespace Orchard.Core.Containers.Settings {
|
||||
builder.WithSetting("ContainerTypePartSettings.RestrictItemContentTypes", viewModel.RestrictItemContentTypes.ToString());
|
||||
builder.WithSetting("ContainerTypePartSettings.EnablePositioning", viewModel.EnablePositioning.ToString());
|
||||
builder.WithSetting("ContainerTypePartSettings.AdminListViewName", viewModel.AdminListViewName);
|
||||
builder.WithSetting("ContainerTypePartSettings.DisplayContainerEditor", viewModel.DisplayContainerEditor.ToString());
|
||||
yield return DefinitionTemplate(viewModel);
|
||||
}
|
||||
|
||||
|
@ -16,5 +16,6 @@ namespace Orchard.Core.Containers.ViewModels {
|
||||
|
||||
[UIHint("ListViewPicker")]
|
||||
public string AdminListViewName { get; set; }
|
||||
public bool DisplayContainerEditor { get; set; }
|
||||
}
|
||||
}
|
@ -2,6 +2,11 @@
|
||||
@{
|
||||
Script.Require("ShapesBase");
|
||||
}
|
||||
<fieldset>
|
||||
@Html.CheckBoxFor(m => m.DisplayContainerEditor)
|
||||
@Html.LabelFor(m => m.DisplayContainerEditor, @T("Display settings editor").ToString(), new { @class = "forcheckbox" })
|
||||
<span class="hint">@T("When checked, users can change the settings for each content item.")</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.ItemsShownDefault)">@T("Default Items Shown")</label>
|
||||
@Html.EditorFor(m => m.ItemsShownDefault)
|
||||
|
@ -65,8 +65,7 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||
|
||||
var versionOptions = VersionOptions.Latest;
|
||||
switch (model.Options.ContentsStatus)
|
||||
{
|
||||
switch (model.Options.ContentsStatus) {
|
||||
case ContentsStatus.Published:
|
||||
versionOptions = VersionOptions.Published;
|
||||
break;
|
||||
@ -112,6 +111,10 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
query = _cultureFilter.FilterCulture(query, model.Options.SelectedCulture);
|
||||
}
|
||||
|
||||
if(model.Options.ContentsStatus == ContentsStatus.Owner) {
|
||||
query = query.Where<CommonPartRecord>(cr => cr.OwnerId == Services.WorkContext.CurrentUser.Id);
|
||||
}
|
||||
|
||||
model.Options.SelectedFilter = model.TypeName;
|
||||
model.Options.FilterOptions = GetListableTypes(false)
|
||||
.Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName))
|
||||
|
@ -49,12 +49,12 @@ namespace Orchard.Core.Contents.ViewModels {
|
||||
Created
|
||||
}
|
||||
|
||||
public enum ContentsStatus
|
||||
{
|
||||
public enum ContentsStatus {
|
||||
Draft,
|
||||
Published,
|
||||
AllVersions,
|
||||
Latest
|
||||
Latest,
|
||||
Owner
|
||||
}
|
||||
|
||||
public enum ContentsBulkAction {
|
||||
|
@ -56,6 +56,7 @@
|
||||
</select>
|
||||
<label for="contentResults" class="bulk-order">@T("Filter by")</label>
|
||||
<select id="contentResults" name="Options.ContentsStatus">
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Owner, T("owned by me").ToString())
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Latest, T("latest").ToString())
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Published, T("published").ToString())
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Draft, T("unpublished").ToString())
|
||||
|
@ -69,11 +69,12 @@ namespace Orchard.Core.Settings.Drivers {
|
||||
|
||||
var previousBaseUrl = model.Site.BaseUrl;
|
||||
|
||||
updater.TryUpdateModel(model, Prefix, null, new [] { "Site.SuperUser", "Site.MaxPageSize" });
|
||||
// Update all properties but not SuperUser, MaxPageSize and BaseUrl.
|
||||
updater.TryUpdateModel(model, Prefix, null, new [] { "Site.SuperUser", "Site.MaxPageSize", "Site.BaseUrl", "Site.MaxPagedCount" });
|
||||
|
||||
// only a user with SiteOwner permission can change the site owner
|
||||
if (_authorizer.Authorize(StandardPermissions.SiteOwner)) {
|
||||
updater.TryUpdateModel(model, Prefix, new[] { "Site.SuperUser", "Site.MaxPageSize" }, null);
|
||||
updater.TryUpdateModel(model, Prefix, new[] { "Site.SuperUser", "Site.MaxPageSize", "Site.BaseUrl", "Site.MaxPagedCount" }, null);
|
||||
|
||||
// ensures the super user is fully empty
|
||||
if (String.IsNullOrEmpty(model.SuperUser)) {
|
||||
@ -86,30 +87,30 @@ namespace Orchard.Core.Settings.Drivers {
|
||||
updater.AddModelError("SuperUser", T("The user {0} was not found", model.SuperUser));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the base url is absolute if provided
|
||||
if (!String.IsNullOrWhiteSpace(model.Site.BaseUrl)) {
|
||||
if (!Uri.IsWellFormedUriString(model.Site.BaseUrl, UriKind.Absolute)) {
|
||||
updater.AddModelError("BaseUrl", T("The base url must be absolute."));
|
||||
}
|
||||
// ensure the base url is absolute if provided
|
||||
if (!String.IsNullOrWhiteSpace(model.Site.BaseUrl)) {
|
||||
if (!Uri.IsWellFormedUriString(model.Site.BaseUrl, UriKind.Absolute)) {
|
||||
updater.AddModelError("BaseUrl", T("The base url must be absolute."));
|
||||
}
|
||||
// if the base url has been modified, try to ping it
|
||||
else if (!String.Equals(previousBaseUrl, model.Site.BaseUrl, StringComparison.OrdinalIgnoreCase)) {
|
||||
try {
|
||||
var request = WebRequest.Create(model.Site.BaseUrl) as HttpWebRequest;
|
||||
if (request != null) {
|
||||
using (request.GetResponse() as HttpWebResponse) {}
|
||||
else if (!String.Equals(previousBaseUrl, model.Site.BaseUrl, StringComparison.OrdinalIgnoreCase)) {
|
||||
try {
|
||||
var request = WebRequest.Create(model.Site.BaseUrl) as HttpWebRequest;
|
||||
if (request != null) {
|
||||
using (request.GetResponse() as HttpWebResponse) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
_notifier.Warning(T("The base url you entered could not be requested from current location."));
|
||||
Logger.Warning(ex, "Could not query base url: {0}", model.Site.BaseUrl);
|
||||
}
|
||||
_notifier.Warning(T("The base url you entered could not be requested from current location."));
|
||||
Logger.Warning(ex, "Could not query base url: {0}", model.Site.BaseUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ContentShape("Parts_Settings_SiteSettingsPart",
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Settings.SiteSettingsPart", Model: model, Prefix: Prefix));
|
||||
|
@ -16,7 +16,10 @@
|
||||
</div>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.BaseUrl)">@T("Base URL")</label>
|
||||
@Html.TextBoxFor(m => m.BaseUrl, new { @class = "text medium is-url" })
|
||||
@Html.TextBoxFor(m => m.BaseUrl,
|
||||
(object)(AuthorizedFor(Orchard.Security.StandardPermissions.SiteOwner)
|
||||
? (dynamic)new { @class = "text medium is-url" }
|
||||
: (dynamic)new { @class = "text medium is-url", @readonly = "readonly" }))
|
||||
<span class="hint">@T("Enter the fully qualified base URL of the web site.")</span>
|
||||
<span class="hint">@T("e.g., http://localhost:30320/orchardlocal, http://www.yourdomain.com")</span>
|
||||
</div>
|
||||
@ -45,14 +48,15 @@
|
||||
@Html.EditorFor(x => x.PageTitleSeparator)
|
||||
@Html.ValidationMessage("PageTitleSeparator", "*")
|
||||
</div>
|
||||
@if (AuthorizedFor(Orchard.Security.StandardPermissions.SiteOwner)) {
|
||||
<div>
|
||||
<label for="SuperUser">@T("Super user")</label>
|
||||
@Html.EditorFor(x => x.SuperUser)
|
||||
@Html.TextBoxFor(x => x.SuperUser,
|
||||
(object)(AuthorizedFor(Orchard.Security.StandardPermissions.SiteOwner)
|
||||
? (dynamic)new { @class = "text single-line" }
|
||||
: (dynamic)new { @class = "text single-line", @readonly = "readonly" }))
|
||||
@Html.ValidationMessage("SuperUser", "*")
|
||||
<span class="hint">@T("Enter an existing account name, or nothing if you don't want a Super user account")</span>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<label for="SiteDebugMode">@T("Resource Debug Mode")</label>
|
||||
@Html.DropDownList("ResourceDebugMode", resourceDebugMode)
|
||||
|
@ -319,9 +319,12 @@ namespace Orchard.Core.Shapes {
|
||||
var progress = 1;
|
||||
var flatPositionComparer = new FlatPositionComparer();
|
||||
var ordering = unordered.Select(item => {
|
||||
var position = (item == null || item.GetType().GetProperty("Metadata") == null || item.Metadata.GetType().GetProperty("Position") == null)
|
||||
? null
|
||||
: item.Metadata.Position;
|
||||
string position = null;
|
||||
var itemPosition = item as IPositioned;
|
||||
if (itemPosition != null) {
|
||||
position = itemPosition.Position;
|
||||
}
|
||||
|
||||
return new { item, position };
|
||||
}).ToList();
|
||||
|
||||
|
@ -236,7 +236,13 @@
|
||||
}
|
||||
|
||||
if (_this.filter("[itemprop~='RemoveUrl']").length == 1) {
|
||||
if (!confirm(confirmRemoveMessage)) {
|
||||
// use a custom message if its set in data-message
|
||||
var dataMessage = _this.data('message');
|
||||
if (dataMessage === undefined) {
|
||||
dataMessage = confirmRemoveMessage;
|
||||
}
|
||||
|
||||
if (!confirm(dataMessage)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -73,6 +74,10 @@
|
||||
<Name>Orchard.Core</Name>
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.MediaLibrary\Orchard.MediaLibrary.csproj">
|
||||
<Project>{73a7688a-5bd3-4f7e-adfa-ce36c5a10e3b}</Project>
|
||||
<Name>Orchard.MediaLibrary</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Admin\Images\grippie.png" />
|
||||
|
@ -5,70 +5,72 @@
|
||||
editors.each(function() {
|
||||
|
||||
var idPostfix = $(this).attr('id').substr('wmd-input'.length);
|
||||
|
||||
|
||||
var editor = new Markdown.Editor(converter, idPostfix, {
|
||||
handler: function() { window.open("http://daringfireball.net/projects/markdown/syntax"); }
|
||||
});
|
||||
|
||||
editor.hooks.set("insertImageDialog", function(callback) {
|
||||
// see if there's an image selected that they intend on editing
|
||||
var wmd = $('#wmd-input' + idPostfix);
|
||||
if (Boolean($(this).data("manage-media"))) {
|
||||
editor.hooks.set("insertImageDialog", function (callback) {
|
||||
// see if there's an image selected that they intend on editing
|
||||
var wmd = $('#wmd-input' + idPostfix);
|
||||
|
||||
var editImage, content = wmd.selection ? wmd.selection.createRange().text : null;
|
||||
var adminIndex = location.href.toLowerCase().indexOf("/admin/");
|
||||
if (adminIndex === -1) return;
|
||||
var url = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary?dialog=true";
|
||||
$.colorbox({
|
||||
href: url,
|
||||
iframe: true,
|
||||
reposition: true,
|
||||
width: "90%",
|
||||
height: "90%",
|
||||
onLoad: function () {
|
||||
// hide the scrollbars from the main window
|
||||
$('html, body').css('overflow', 'hidden');
|
||||
},
|
||||
onClosed: function () {
|
||||
$('html, body').css('overflow', '');
|
||||
var editImage, content = wmd.selection ? wmd.selection.createRange().text : null;
|
||||
var adminIndex = location.href.toLowerCase().indexOf("/admin/");
|
||||
if (adminIndex === -1) return;
|
||||
var url = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary?dialog=true";
|
||||
$.colorbox({
|
||||
href: url,
|
||||
iframe: true,
|
||||
reposition: true,
|
||||
width: "90%",
|
||||
height: "90%",
|
||||
onLoad: function () {
|
||||
// hide the scrollbars from the main window
|
||||
$('html, body').css('overflow', 'hidden');
|
||||
},
|
||||
onClosed: function () {
|
||||
$('html, body').css('overflow', '');
|
||||
|
||||
var selectedData = $.colorbox.selectedData;
|
||||
var selectedData = $.colorbox.selectedData;
|
||||
|
||||
if (selectedData == null) // Dialog cancelled, do nothing
|
||||
return;
|
||||
if (selectedData == null) // Dialog cancelled, do nothing
|
||||
return;
|
||||
|
||||
var newContent = '';
|
||||
for (var i = 0; i < selectedData.length; i++) {
|
||||
var renderMedia = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary/MediaItem/" + selectedData[i].id + "?displayType=Raw";
|
||||
$.ajax({
|
||||
async: false,
|
||||
type: 'GET',
|
||||
url: renderMedia,
|
||||
success: function (data) {
|
||||
newContent += data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var result = $.parseHTML(newContent);
|
||||
var img = $(result).filter('img');
|
||||
// if this is an image, use the callback which will format it in markdown
|
||||
if (img.length > 0 && img.attr('src')) {
|
||||
callback(img.attr('src'));
|
||||
}
|
||||
|
||||
// otherwise, insert the raw HTML
|
||||
else {
|
||||
if (wmd.selection) {
|
||||
wmd.selection.replace('.*', newContent);
|
||||
} else {
|
||||
wmd.text(newContent);
|
||||
var newContent = '';
|
||||
for (var i = 0; i < selectedData.length; i++) {
|
||||
var renderMedia = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary/MediaItem/" + selectedData[i].id + "?displayType=Raw";
|
||||
$.ajax({
|
||||
async: false,
|
||||
type: 'GET',
|
||||
url: renderMedia,
|
||||
success: function (data) {
|
||||
newContent += data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var result = $.parseHTML(newContent);
|
||||
var img = $(result).filter('img');
|
||||
// if this is an image, use the callback which will format it in markdown
|
||||
if (img.length > 0 && img.attr('src')) {
|
||||
callback(img.attr('src'));
|
||||
}
|
||||
|
||||
// otherwise, insert the raw HTML
|
||||
else {
|
||||
if (wmd.selection) {
|
||||
wmd.selection.replace('.*', newContent);
|
||||
} else {
|
||||
wmd.text(newContent);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
editor.run();
|
||||
});
|
||||
|
@ -21,7 +21,8 @@
|
||||
{"id", "wmd-input" + "-" + idPostfix},
|
||||
{"class", "wmd-input"},
|
||||
{"data-mediapicker-uploadpath", Model.AddMediaPath},
|
||||
{"data-mediapicker-title", T("Insert/Update Media")}
|
||||
{"data-mediapicker-title", T("Insert/Update Media")},
|
||||
{"data-manage-media", AuthorizedFor(Orchard.MediaLibrary.Permissions.ManageMediaContent) ? "true" : "false" }
|
||||
};
|
||||
|
||||
// The markdown editor itself doesn't seem to (yet) support autofocus, but we'll set it on the textarea nonetheless.
|
||||
|
@ -144,7 +144,7 @@ namespace Orchard.AntiSpam.Controllers {
|
||||
if (spam != null) {
|
||||
spam.As<SpamFilterPart>().Status = SpamStatus.Spam;
|
||||
_spamService.ReportSpam(spam.As<SpamFilterPart>());
|
||||
Services.ContentManager.Publish(spam);
|
||||
Services.ContentManager.Unpublish(spam);
|
||||
}
|
||||
|
||||
return this.RedirectLocal(returnUrl, "~/");
|
||||
@ -158,7 +158,7 @@ namespace Orchard.AntiSpam.Controllers {
|
||||
var spam = Services.ContentManager.Get(id, VersionOptions.Latest);
|
||||
if (spam != null) {
|
||||
spam.As<SpamFilterPart>().Status = SpamStatus.Ham;
|
||||
_spamService.ReportSpam(spam.As<SpamFilterPart>());
|
||||
_spamService.ReportHam(spam.As<SpamFilterPart>());
|
||||
Services.ContentManager.Publish(spam);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Orchard.AntiSpam.Models;
|
||||
using Orchard.AntiSpam.Services;
|
||||
using Orchard.AntiSpam.Settings;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
@ -8,11 +7,9 @@ using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AntiSpam.Drivers {
|
||||
public class SpamFilterPartDriver : ContentPartDriver<SpamFilterPart> {
|
||||
private readonly ISpamService _spamService;
|
||||
private const string TemplateName = "Parts/SpamFilter";
|
||||
|
||||
public SpamFilterPartDriver(IOrchardServices services, ISpamService spamService) {
|
||||
_spamService = spamService;
|
||||
public SpamFilterPartDriver(IOrchardServices services) {
|
||||
T = NullLocalizer.Instance;
|
||||
Services = services;
|
||||
}
|
||||
@ -25,8 +22,6 @@ namespace Orchard.AntiSpam.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(SpamFilterPart part, ContentManagement.IUpdateModel updater, dynamic shapeHelper) {
|
||||
part.Status = _spamService.CheckForSpam(part);
|
||||
|
||||
if (part.Settings.GetModel<SpamFilterPartSettings>().DeleteSpam) {
|
||||
updater.AddModelError("Spam", T("Spam detected."));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Orchard.AntiSpam.Models;
|
||||
|
||||
using Orchard.AntiSpam.Services;
|
||||
using Orchard.AntiSpam.Settings;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Data;
|
||||
@ -7,14 +7,22 @@ using Orchard.Data;
|
||||
namespace Orchard.AntiSpam.Handlers {
|
||||
public class SpamFilterPartHandler : ContentHandler {
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private readonly ISpamService _spamService;
|
||||
|
||||
public SpamFilterPartHandler(
|
||||
IRepository<SpamFilterPartRecord> repository,
|
||||
ITransactionManager transactionManager
|
||||
ITransactionManager transactionManager,
|
||||
ISpamService spamService
|
||||
) {
|
||||
_transactionManager = transactionManager;
|
||||
_spamService = spamService;
|
||||
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
|
||||
OnCreating<SpamFilterPart>((context, part) => {
|
||||
part.Status = _spamService.CheckForSpam(part);
|
||||
});
|
||||
|
||||
OnPublishing<SpamFilterPart>((context, part) => {
|
||||
if (part.Status == SpamStatus.Spam) {
|
||||
if (part.Settings.GetModel<SpamFilterPartSettings>().DeleteSpam) {
|
||||
|
@ -126,6 +126,7 @@ namespace Orchard.AntiSpam.Services {
|
||||
CommentAuthorEmail = _tokenizer.Replace(settings.CommentAuthorEmailPattern, data),
|
||||
CommentAuthorUrl = _tokenizer.Replace(settings.CommentAuthorUrlPattern, data),
|
||||
CommentContent = _tokenizer.Replace(settings.CommentContentPattern, data),
|
||||
CommentType = part.ContentItem.ContentType.ToLower()
|
||||
};
|
||||
|
||||
if(workContext.HttpContext != null) {
|
||||
|
@ -117,7 +117,7 @@ namespace Orchard.Comments.Drivers {
|
||||
|
||||
// prevent users from commenting on a closed thread by hijacking the commentedOn property
|
||||
var commentsPart = commentedOn.As<CommentsPart>();
|
||||
if (!commentsPart.CommentsActive) {
|
||||
if (commentsPart == null || !commentsPart.CommentsActive) {
|
||||
_orchardServices.TransactionManager.Cancel();
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
|
@ -118,7 +118,8 @@ namespace Orchard.Comments.Services {
|
||||
}
|
||||
|
||||
public void DeleteComment(int commentId) {
|
||||
_orchardServices.ContentManager.Remove(_orchardServices.ContentManager.Get<CommentPart>(commentId).ContentItem);
|
||||
// Get latest because the comment may be unpublished if the anti-spam module has caught it
|
||||
_orchardServices.ContentManager.Remove(_orchardServices.ContentManager.Get<CommentPart>(commentId, VersionOptions.Latest).ContentItem);
|
||||
}
|
||||
|
||||
public bool CommentsDisabledForCommentedContent(int id) {
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
<fieldset class="action">
|
||||
<button class="primaryAction" type="submit" name="submit.Save" value="Save">@T("Save")</button>
|
||||
<button class="primaryAction" type="submit" name="submit.Restore" value="Restore">@T("Restore")</button>
|
||||
<button class="primaryAction" type="submit" name="submit.Restore" value="Restore" itemprop="RemoveUrl" data-message="@T("Are you sure you want to restore these placements?")">@T("Restore")</button>
|
||||
</fieldset>
|
||||
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ namespace Orchard.DynamicForms.Drivers {
|
||||
var runtimeValues = GetRuntimeValues(element);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(optionLabel)) {
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel };
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel, Value = string.Empty };
|
||||
}
|
||||
|
||||
if (queryId == null)
|
||||
|
@ -138,7 +138,7 @@ namespace Orchard.DynamicForms.Drivers {
|
||||
var runtimeValues = GetRuntimeValues(element);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(optionLabel)) {
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel };
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel, Value = string.Empty };
|
||||
}
|
||||
|
||||
if (taxonomyId == null)
|
||||
|
@ -8,34 +8,34 @@
|
||||
<label for="@Html.FieldIdFor(m => m.Value)" @if(settings.Required) { <text>class="required"</text> }>@Model.DisplayName</label>
|
||||
@switch (settings.ListMode) {
|
||||
case ListMode.Dropdown:
|
||||
@Html.DropDownListFor(m => m.Value, new SelectList(options, Model.Value))
|
||||
@Html.DropDownListFor(m => m.Value, new SelectList(options, Model.Value), settings.Required ? new {required = "required"} : null)
|
||||
break;
|
||||
|
||||
case ListMode.Radiobutton:
|
||||
foreach (var option in options) {
|
||||
if (string.IsNullOrWhiteSpace(option)) {
|
||||
<label>@Html.RadioButton("Value", "", string.IsNullOrWhiteSpace(Model.Value))<i>@T("unset")</i></label>
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(option)) {
|
||||
<label>@Html.RadioButton("Value", "", string.IsNullOrWhiteSpace(Model.Value), settings.Required ? new {required = "required"} : null)<i>@T("unset")</i></label>
|
||||
}
|
||||
else {
|
||||
<label>@Html.RadioButton("Value", option, (option == Model.Value))@option</label>
|
||||
}
|
||||
<label>@Html.RadioButton("Value", option, (option == Model.Value), settings.Required ? new {required = "required"} : null)@option</label>
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ListMode.Listbox:
|
||||
<input name="@Html.FieldNameFor(m => m.SelectedValues)" type="hidden" />
|
||||
@Html.ListBoxFor(m => m.SelectedValues, new MultiSelectList(options, Model.SelectedValues))
|
||||
break;
|
||||
@Html.ListBoxFor(m => m.SelectedValues, new MultiSelectList(options, Model.SelectedValues), settings.Required ? new {required = "required"} : null)
|
||||
break;
|
||||
|
||||
case ListMode.Checkbox:
|
||||
int index = 0;
|
||||
int index = 0;
|
||||
<input name="@Html.FieldNameFor(m => m.SelectedValues)" type="hidden" />
|
||||
foreach (var option in options) {
|
||||
index++;
|
||||
if (!string.IsNullOrWhiteSpace(option)) {
|
||||
<div>
|
||||
<input type="checkbox" name="@Html.FieldNameFor(m => m.SelectedValues)" value="@option" @((Model.SelectedValues != null && Model.SelectedValues.Contains(option)) ? "checked=\"checked\"" : "") class="check-box" id="@Html.FieldIdFor(m => m.SelectedValues)-@index" />
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.SelectedValues)-@index">@T(option)</label>
|
||||
<input type="checkbox" name="@Html.FieldNameFor(m => m.SelectedValues)" value="@option" @((Model.SelectedValues != null && Model.SelectedValues.Contains(option)) ? "checked=\"checked\"" : "") class="check-box" id="@Html.FieldIdFor(m => m.SelectedValues)-@index" @if(settings.Required) {<text> required="required"</text> } />
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.SelectedValues)-@index">@T(option)</label>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,9 @@
|
||||
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.Value)" @if(Model.Settings.Required) { <text>class="required"</text> }>@Model.Field.DisplayName</label>
|
||||
@Html.TextBoxFor(m => m.Value, new { @class = "text small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture) })
|
||||
@(Model.Settings.Required
|
||||
? Html.TextBoxFor(m => m.Value, new {@class = "text-small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture), required = "required"})
|
||||
: Html.TextBoxFor(m => m.Value, new {@class = "text-small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture)}))
|
||||
@Html.ValidationMessageFor(m => m.Value)
|
||||
@if (HasText(Model.Settings.Hint)) {
|
||||
<span class="hint">@Model.Settings.Hint</span>
|
||||
|
@ -45,6 +45,15 @@ namespace Orchard.ImageEditor.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult Edit(string folderPath, string filename) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var media = Services.ContentManager.Query<MediaPart, MediaPartRecord>().Where(x => x.FolderPath == folderPath && x.FileName == filename).Slice(0, 1).FirstOrDefault();
|
||||
|
||||
if (media == null) {
|
||||
@ -64,12 +73,21 @@ namespace Orchard.ImageEditor.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Upload(int id, string content, int width, int height) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var media = Services.ContentManager.Get(id).As<MediaPart>();
|
||||
|
||||
if (media == null) {
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
const string signature = "data:image/jpeg;base64,";
|
||||
|
||||
if (!content.StartsWith(signature, StringComparison.OrdinalIgnoreCase)) {
|
||||
@ -96,7 +114,7 @@ namespace Orchard.ImageEditor.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Proxy(string url) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return HttpNotFound();
|
||||
|
||||
var sslFailureCallback = new RemoteCertificateValidationCallback((o, cert, chain, errors) => true);
|
||||
|
@ -11,9 +11,9 @@ namespace Orchard.Layouts {
|
||||
builder
|
||||
.AddImageSet("layouts")
|
||||
.Add(T("Layouts"), "8.5", layouts => layouts
|
||||
.Action("List", "Admin", new {id = "Layout", area = "Contents"})
|
||||
.Action("List", "Admin", new {id = "Layout", area = "Contents"}).Permission(Permissions.ManageLayouts)
|
||||
.LinkToFirstChild(false)
|
||||
.Add(T("Elements"), "1", elements => elements.Action("Index", "BlueprintAdmin", new {area = "Orchard.Layouts"})));
|
||||
.Add(T("Elements"), "1", elements => elements.Action("Index", "BlueprintAdmin", new {area = "Orchard.Layouts"}).Permission(Permissions.ManageLayouts)));
|
||||
}
|
||||
}
|
||||
}
|
@ -74,45 +74,6 @@
|
||||
return host.addElement(contentType);
|
||||
};
|
||||
|
||||
$scope.toggleInlineEditing = function () {
|
||||
if (!$scope.element.inlineEditingIsActive) {
|
||||
$scope.element.inlineEditingIsActive = true;
|
||||
$element.find(".layout-toolbar-container").show();
|
||||
var selector = "#layout-editor-" + $scope.$id + " .layout-html .layout-content-markup[data-templated=false]";
|
||||
var firstContentEditorId = $(selector).first().attr("id");
|
||||
tinymce.init({
|
||||
selector: selector,
|
||||
theme: "modern",
|
||||
schema: "html5",
|
||||
plugins: [
|
||||
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
|
||||
"searchreplace wordcount visualblocks visualchars code fullscreen",
|
||||
"insertdatetime media nonbreaking table contextmenu directionality",
|
||||
"emoticons template paste textcolor colorpicker textpattern",
|
||||
"fullscreen autoresize"
|
||||
],
|
||||
toolbar: "undo redo cut copy paste | bold italic | bullist numlist outdent indent formatselect | alignleft aligncenter alignright alignjustify ltr rtl | link unlink charmap | code fullscreen close",
|
||||
convert_urls: false,
|
||||
valid_elements: "*[*]",
|
||||
// Shouldn't be needed due to the valid_elements setting, but TinyMCE would strip script.src without it.
|
||||
extended_valid_elements: "script[type|defer|src|language]",
|
||||
statusbar: false,
|
||||
skin: "orchardlightgray",
|
||||
inline: true,
|
||||
fixed_toolbar_container: "#layout-editor-" + $scope.$id + " .layout-toolbar-container",
|
||||
init_instance_callback: function (editor) {
|
||||
if (editor.id == firstContentEditorId)
|
||||
tinymce.execCommand("mceFocus", false, editor.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
tinymce.remove("#layout-editor-" + $scope.$id + " .layout-content-markup");
|
||||
$element.find(".layout-toolbar-container").hide();
|
||||
$scope.element.inlineEditingIsActive = false;
|
||||
}
|
||||
};
|
||||
|
||||
$(document).on("cut copy paste", function (e) {
|
||||
// If the pseudo clipboard was already invoked (which happens on the first clipboard
|
||||
// operation after page load even if native clipboard support exists) then sit this
|
||||
@ -164,23 +125,12 @@
|
||||
element.find(".layout-toolbar-container").click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
// Intercept mousedown on editor while in inline editing mode to
|
||||
// prevent current editor from losing focus.
|
||||
element.mousedown(function (e) {
|
||||
if (scope.element.inlineEditingIsActive) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
})
|
||||
// Unfocus and unselect everything on click outside of canvas.
|
||||
$(window).click(function (e) {
|
||||
// Except when in inline editing mode.
|
||||
if (!scope.element.inlineEditingIsActive) {
|
||||
scope.$apply(function () {
|
||||
scope.element.activeElement = null;
|
||||
scope.element.focusedElement = null;
|
||||
});
|
||||
}
|
||||
scope.$apply(function () {
|
||||
scope.element.activeElement = null;
|
||||
scope.element.focusedElement = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -35,13 +35,6 @@
|
||||
templateUrl: environment.templateUrl("Html"),
|
||||
replace: true,
|
||||
link: function (scope, element) {
|
||||
// Mouse down events must not be intercepted by drag and drop while inline editing is active,
|
||||
// otherwise clicks in inline editors will have no effect.
|
||||
element.find(".layout-content-markup").mousedown(function (e) {
|
||||
if (scope.element.editor.inlineEditingIsActive) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
var resetFocus = false;
|
||||
var element = $scope.element;
|
||||
|
||||
if (element.editor.isDragging || element.editor.inlineEditingIsActive)
|
||||
if (element.editor.isDragging)
|
||||
return;
|
||||
|
||||
// If native clipboard support exists, the pseudo-clipboard will have been disabled.
|
||||
|
@ -9,7 +9,6 @@
|
||||
this.focusedElement = null;
|
||||
this.dropTargetElement = null;
|
||||
this.isDragging = false;
|
||||
this.inlineEditingIsActive = false;
|
||||
this.isResizing = false;
|
||||
|
||||
this.resetToolboxElements = function () {
|
||||
|
@ -57,7 +57,7 @@
|
||||
this.setIsActive = function (value) {
|
||||
if (!this.editor)
|
||||
return;
|
||||
if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing)
|
||||
if (this.editor.isDragging || this.editor.isResizing)
|
||||
return;
|
||||
|
||||
if (value)
|
||||
@ -81,7 +81,7 @@
|
||||
return;
|
||||
if (this.isTemplated && !this.allowSealedFocus())
|
||||
return;
|
||||
if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing)
|
||||
if (this.editor.isDragging || this.editor.isResizing)
|
||||
return;
|
||||
|
||||
this.editor.focusedElement = this;
|
||||
|
@ -34,7 +34,8 @@ namespace Orchard.Layouts.Controllers {
|
||||
ICultureAccessor cultureAccessor,
|
||||
IShapeFactory shapeFactory,
|
||||
ITransactionManager transactionManager,
|
||||
ISignals signals) {
|
||||
ISignals signals,
|
||||
IOrchardServices orchardServices) {
|
||||
|
||||
_elementBlueprintService = elementBlueprintService;
|
||||
_notifier = notifier;
|
||||
@ -43,12 +44,19 @@ namespace Orchard.Layouts.Controllers {
|
||||
_shapeFactory = shapeFactory;
|
||||
_transactionManager = transactionManager;
|
||||
_signals = signals;
|
||||
Services = orchardServices;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Index() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprints = _elementBlueprintService.GetBlueprints().ToArray();
|
||||
var viewModel = new BlueprintsIndexViewModel {
|
||||
Blueprints = blueprints
|
||||
@ -57,6 +65,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Browse() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var categories = RemoveBlueprints(_elementManager.GetCategories(DescribeElementsContext.Empty)).ToArray();
|
||||
var viewModel = new BrowseElementsViewModel {
|
||||
Categories = categories
|
||||
@ -65,6 +77,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Create(string id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (String.IsNullOrWhiteSpace(id))
|
||||
return RedirectToAction("Browse");
|
||||
|
||||
@ -80,6 +96,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Create(string id, CreateElementBlueprintViewModel model) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, id);
|
||||
var baseElement = _elementManager.ActivateElement(descriptor);
|
||||
@ -100,7 +120,11 @@ namespace Orchard.Layouts.Controllers {
|
||||
return RedirectToAction("Edit", new { id = blueprint.Id });
|
||||
}
|
||||
|
||||
public ViewResult Edit(int id) {
|
||||
public ActionResult Edit(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@ -125,6 +149,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
[HttpPost]
|
||||
[ValidateInput(false)]
|
||||
public ActionResult Edit(int id, ElementDataViewModel model) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@ -154,6 +182,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Properties(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@ -171,6 +203,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Properties(int id, ElementBlueprintPropertiesViewModel model) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@ -191,7 +227,12 @@ namespace Orchard.Layouts.Controllers {
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
|
||||
if (blueprint == null)
|
||||
@ -204,7 +245,12 @@ namespace Orchard.Layouts.Controllers {
|
||||
|
||||
[FormValueRequired("submit.BulkEdit")]
|
||||
[ActionName("Index")]
|
||||
[HttpPost]
|
||||
public ActionResult BulkDelete(IEnumerable<int> blueprintIds) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (blueprintIds == null || !blueprintIds.Any()) {
|
||||
_notifier.Error(T("Please select the blueprints to delete."));
|
||||
}
|
||||
|
@ -142,18 +142,7 @@ namespace Orchard.Layouts.Controllers {
|
||||
_objectStore.Set(session, state);
|
||||
return RedirectToAction("Edit", new {session = session});
|
||||
}
|
||||
|
||||
public RedirectToRouteResult Add(string session, string typeName, int? contentId = null, string contentType = null) {
|
||||
var state = new ElementSessionState {
|
||||
TypeName = typeName,
|
||||
ContentId = contentId,
|
||||
ContentType = contentType
|
||||
};
|
||||
|
||||
_objectStore.Set(session, state);
|
||||
return RedirectToAction("Edit", new { session = session });
|
||||
}
|
||||
|
||||
|
||||
public ViewResult Edit(string session) {
|
||||
var sessionState = _objectStore.Get<ElementSessionState>(session);
|
||||
var contentId = sessionState.ContentId;
|
||||
|
@ -6,6 +6,7 @@ using Orchard.ContentManagement;
|
||||
using Orchard.Layouts.Elements;
|
||||
using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Services;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Admin;
|
||||
|
||||
namespace Orchard.Layouts.Controllers {
|
||||
@ -15,15 +16,25 @@ namespace Orchard.Layouts.Controllers {
|
||||
private readonly ILayoutManager _layoutManager;
|
||||
private readonly ILayoutModelMapper _mapper;
|
||||
|
||||
public LayoutController(IContentManager contentManager, ILayoutManager layoutManager, ILayoutModelMapper mapper) {
|
||||
public LayoutController(
|
||||
IContentManager contentManager,
|
||||
ILayoutManager layoutManager,
|
||||
ILayoutModelMapper mapper,
|
||||
IOrchardServices orchardServices) {
|
||||
|
||||
_contentManager = contentManager;
|
||||
_layoutManager = layoutManager;
|
||||
_mapper = mapper;
|
||||
Services = orchardServices;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
[HttpPost, ValidateInput(enableValidation: false)]
|
||||
public ContentResult ApplyTemplate(int? templateId = null, string layoutData = null, int? contentId = null, string contentType = null) {
|
||||
public ActionResult ApplyTemplate(int? templateId = null, string layoutData = null, int? contentId = null, string contentType = null) {
|
||||
var template = templateId != null ? _layoutManager.GetLayout(templateId.Value) : null;
|
||||
var templateElements = template != null ? _layoutManager.LoadElements(template).ToList() : default(IEnumerable<Element>);
|
||||
var describeContext = CreateDescribeElementsContext(contentId, contentType);
|
||||
|
@ -33,7 +33,6 @@ namespace Orchard.Layouts {
|
||||
.WithPart("LayoutPart", p => p
|
||||
.WithSetting("LayoutTypePartSettings.IsTemplate", "True"))
|
||||
.DisplayedAs("Layout")
|
||||
.Listable()
|
||||
.Draftable());
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("LayoutWidget", type => type
|
||||
|
@ -368,6 +368,7 @@
|
||||
<Compile Include="Helpers\PrefixHelper.cs" />
|
||||
<Compile Include="Helpers\JsonHelper.cs" />
|
||||
<Compile Include="Helpers\StringHelper.cs" />
|
||||
<Compile Include="Permissions.cs" />
|
||||
<Compile Include="Recipes\Builders\CustomElementsStep.cs" />
|
||||
<Compile Include="Recipes\Executors\CustomElementsStep.cs" />
|
||||
<Compile Include="Providers\BlueprintElementHarvester.cs" />
|
||||
|
40
src/Orchard.Web/Modules/Orchard.Layouts/Permissions.cs
Normal file
40
src/Orchard.Web/Modules/Orchard.Layouts/Permissions.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Layouts {
|
||||
public class Permissions : IPermissionProvider {
|
||||
public static readonly Permission ManageLayouts = new Permission { Description = "Managing Layouts", Name = "ManageLayouts" };
|
||||
|
||||
public virtual Feature Feature { get; set; }
|
||||
|
||||
public IEnumerable<Permission> GetPermissions() {
|
||||
return new[] {
|
||||
ManageLayouts,
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
|
||||
return new[] {
|
||||
new PermissionStereotype {
|
||||
Name = "Administrator",
|
||||
Permissions = new[] { ManageLayouts }
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Editor",
|
||||
Permissions = new[] { ManageLayouts }
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Moderator",
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Author"
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Contributor",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
||||
@foreach (var contentItemShape in Model.ContentItems) {
|
||||
var contentItem = (ContentItem)contentItemShape.ContentItem;
|
||||
var displayTextHtmlString = Html.ItemDisplayText(contentItem);
|
||||
var displayText = displayTextHtmlString != null ? displayTextHtmlString.ToString() : T("-").ToString();
|
||||
var displayText = displayTextHtmlString != null ? (IHtmlString)displayTextHtmlString : T("-");
|
||||
<div class="layout-snippet">
|
||||
@displayText
|
||||
</div>
|
||||
|
@ -1,10 +1,6 @@
|
||||
<div class="layout-toolbox-wrapper">
|
||||
<div class="layout-toolbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-checked="element.inlineEditingIsActive" ng-click="toggleInlineEditing()" />
|
||||
@T("Edit HTML content inline")
|
||||
</label>
|
||||
<ul class="layout-toolbox-groups" ng-hide="element.inlineEditingIsActive">
|
||||
<ul class="layout-toolbox-groups">
|
||||
<li class="layout-toolbox-group" ng-class="{collapsed: layoutIsCollapsed}">
|
||||
<a href="#" class="layout-toolbox-group-heading" ng-click="toggleLayoutIsCollapsed($event)">@T("Layout")</a>
|
||||
<ul class="layout-toolbox-items">
|
||||
|
@ -53,10 +53,7 @@ namespace Orchard.Localization.Controllers {
|
||||
var contentItemTranslation = _contentManager.New<LocalizationPart>(masterContentItem.ContentType);
|
||||
contentItemTranslation.MasterContentItem = masterContentItem;
|
||||
|
||||
// build the editor using the master content item so that
|
||||
// the form is pre-populated with the original values
|
||||
|
||||
var content = _contentManager.BuildEditor(masterContentItem);
|
||||
var content = _contentManager.BuildEditor(contentItemTranslation);
|
||||
|
||||
return View(content);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary {
|
||||
builder.AddImageSet("media-library")
|
||||
.Add(T("Media"), "6",
|
||||
menu => menu.Add(T("Media"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent)));
|
||||
.Permission(Permissions.ManageOwnMedia)));
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ using Orchard.Themes;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Validation;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.MediaLibrary.Controllers {
|
||||
[ValidateInput(false)]
|
||||
@ -41,17 +42,21 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public ActionResult Index(string folderPath = "", bool dialog = false) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// If the user is trying to access a folder above his boundaries, redirect him to his home folder
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return RedirectToAction("Index", new { folderPath = rootMediaFolder.MediaPath, dialog });
|
||||
}
|
||||
|
||||
// let other modules enhance the ui by providing custom navigation and actions
|
||||
var explorer = Services.ContentManager.New("MediaLibraryExplorer");
|
||||
explorer.Weld(new MediaLibraryExplorerPart());
|
||||
|
||||
var explorerShape = Services.ContentManager.BuildDisplay(explorer);
|
||||
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
|
||||
var viewModel = new MediaManagerIndexViewModel {
|
||||
DialogMode = dialog,
|
||||
FolderPath = folderPath,
|
||||
@ -73,7 +78,7 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Import(string folderPath) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot import media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot import media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var mediaProviderMenu = _navigationManager.BuildMenu("mediaproviders");
|
||||
@ -91,9 +96,20 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult MediaItems(string folderPath, int skip = 0, int count = 0, string order = "created", string mediaType = "") {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
var model = new MediaManagerMediaItemsViewModel {
|
||||
MediaItems = new List<MediaManagerMediaItemViewModel>(),
|
||||
MediaItemsCount = 0,
|
||||
FolderPath = folderPath
|
||||
};
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(folderPath, skip, count, order, mediaType, VersionOptions.Latest);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(folderPath, mediaType, VersionOptions.Latest);
|
||||
|
||||
@ -113,9 +129,19 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult ChildFolders(string folderPath = null) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot get child folder listing")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot get child folder listing")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
var model = new MediaManagerChildFoldersViewModel {
|
||||
Children = new IMediaFolder[0]
|
||||
};
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var viewModel = new MediaManagerChildFoldersViewModel {
|
||||
Children = _mediaLibraryService.GetMediaFolders(folderPath)
|
||||
};
|
||||
@ -127,11 +153,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult RecentMediaItems(int skip = 0, int count = 0, string order = "created", string mediaType = "") {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(skip, count, order, mediaType);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(mediaType);
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder().MediaPath;
|
||||
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(rootMediaFolder, skip, count, order, mediaType);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(rootMediaFolder, mediaType);
|
||||
|
||||
|
||||
var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel {
|
||||
@ -149,12 +177,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult MediaItem(int id, string displayType = "SummaryAdmin") {
|
||||
var contentItem = Services.ContentManager.Get(id, VersionOptions.Latest);
|
||||
var contentItem = Services.ContentManager.Get<MediaPart>(id, VersionOptions.Latest);
|
||||
|
||||
if (contentItem == null)
|
||||
return HttpNotFound();
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, contentItem, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, contentItem, T("Cannot view media"))
|
||||
|| !_mediaLibraryService.CanManageMediaFolder(contentItem.FolderPath))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
dynamic model = Services.ContentManager.BuildDisplay(contentItem, displayType);
|
||||
@ -164,13 +193,20 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(int[] mediaItemIds) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't delete media items")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't delete media items")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var mediaItems = Services.ContentManager
|
||||
.Query(VersionOptions.Latest)
|
||||
.ForContentItems(mediaItemIds)
|
||||
.List()
|
||||
.Select(x => x.As<MediaPart>())
|
||||
.Where(x => x != null);
|
||||
|
||||
try {
|
||||
foreach (var media in Services.ContentManager.Query(VersionOptions.Latest).ForContentItems(mediaItemIds).List()) {
|
||||
if (media != null) {
|
||||
Services.ContentManager.Remove(media);
|
||||
foreach (var media in mediaItems) {
|
||||
if (_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) {
|
||||
Services.ContentManager.Remove(media.ContentItem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,12 +220,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Clone(int mediaItemId) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't clone media items")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't clone media items")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
try {
|
||||
var media = Services.ContentManager.Get(mediaItemId).As<MediaPart>();
|
||||
|
||||
if(!_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var newFileName = Path.GetFileNameWithoutExtension(media.FileName) + " Copy" + Path.GetExtension(media.FileName);
|
||||
|
||||
_mediaLibraryService.CopyFile(media.FolderPath, media.FileName, media.FolderPath, newFileName);
|
||||
|
@ -17,10 +17,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
public class ClientStorageController : Controller {
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
|
||||
public ClientStorageController(IMediaLibraryService mediaManagerService, IOrchardServices orchardServices) {
|
||||
public ClientStorageController(
|
||||
IMediaLibraryService mediaManagerService,
|
||||
IContentManager contentManager,
|
||||
IOrchardServices orchardServices) {
|
||||
_mediaLibraryService = mediaManagerService;
|
||||
Services = orchardServices;
|
||||
|
||||
Services = orchardServices;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
@ -42,7 +45,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Upload(string folderPath, string type) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot manage media"))) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,15 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Create(string folderPath) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't create media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// If the user is trying to access a folder above his boundaries, redirect him to his home folder
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return RedirectToAction("Create", new { folderPath = rootMediaFolder.MediaPath });
|
||||
}
|
||||
|
||||
var viewModel = new MediaManagerFolderCreateViewModel {
|
||||
Hierarchy = _mediaLibraryService.GetMediaFolders(folderPath),
|
||||
FolderPath = folderPath
|
||||
@ -45,12 +51,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Create")]
|
||||
public ActionResult Create() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't create media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new MediaManagerFolderCreateViewModel();
|
||||
UpdateModel(viewModel);
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
try {
|
||||
_mediaLibraryService.CreateFolder(viewModel.FolderPath, viewModel.Name);
|
||||
Services.Notifier.Information(T("Media folder created"));
|
||||
@ -66,9 +76,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Edit(string folderPath) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't edit media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var viewModel = new MediaManagerFolderEditViewModel {
|
||||
FolderPath = folderPath,
|
||||
Name = folderPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).Last()
|
||||
@ -80,12 +94,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
[HttpPost, ActionName("Edit")]
|
||||
[FormValueRequired("submit.Save")]
|
||||
public ActionResult Edit() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't edit media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new MediaManagerFolderEditViewModel();
|
||||
UpdateModel(viewModel);
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
try {
|
||||
_mediaLibraryService.RenameFolder(viewModel.FolderPath, viewModel.Name);
|
||||
Services.Notifier.Information(T("Media folder renamed"));
|
||||
@ -101,12 +119,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
[HttpPost, ActionName("Edit")]
|
||||
[FormValueRequired("submit.Delete")]
|
||||
public ActionResult Delete() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't delete media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't delete media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new MediaManagerFolderEditViewModel();
|
||||
UpdateModel(viewModel);
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
}
|
||||
try {
|
||||
_mediaLibraryService.DeleteFolder(viewModel.FolderPath);
|
||||
Services.Notifier.Information(T("Media folder deleted"));
|
||||
@ -122,9 +144,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Move(string folderPath, int[] mediaItemIds) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't move media items")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't move media items")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
foreach (var media in Services.ContentManager.Query().ForPart<MediaPart>().ForContentItems(mediaItemIds).List()) {
|
||||
|
||||
// don't try to rename the file if there is no associated media file
|
||||
|
@ -9,12 +9,18 @@ using Orchard.MediaLibrary.ViewModels;
|
||||
using Orchard.Themes;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.MediaLibrary.Services;
|
||||
|
||||
namespace Orchard.MediaLibrary.Controllers {
|
||||
[Admin, Themed(false)]
|
||||
public class OEmbedController : Controller {
|
||||
public OEmbedController(IOrchardServices services) {
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
|
||||
public OEmbedController(
|
||||
IOrchardServices services,
|
||||
IMediaLibraryService mediaManagerService) {
|
||||
Services = services;
|
||||
_mediaLibraryService = mediaManagerService;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
@ -32,6 +38,15 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
[ActionName("Index")]
|
||||
[ValidateInput(false)]
|
||||
public ActionResult IndexPOST(string folderPath, string url, string type, string title, string html, string thumbnail, string width, string height, string description) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var viewModel = new OEmbedViewModel {
|
||||
Url = url,
|
||||
FolderPath = folderPath
|
||||
|
@ -13,12 +13,19 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
public class WebSearchController : Controller {
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public WebSearchController(IMediaLibraryService mediaManagerService, IContentManager contentManager) {
|
||||
|
||||
public WebSearchController(
|
||||
IMediaLibraryService mediaManagerService,
|
||||
IContentManager contentManager,
|
||||
IOrchardServices orchardServices) {
|
||||
_mediaLibraryService = mediaManagerService;
|
||||
_contentManager = contentManager;
|
||||
|
||||
Services = orchardServices;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public ActionResult Index(string folderPath, string type) {
|
||||
var viewModel = new ImportMediaViewModel {
|
||||
FolderPath = folderPath,
|
||||
@ -30,7 +37,15 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public JsonResult ImagePost(string folderPath, string type, string url) {
|
||||
public ActionResult ImagePost(string folderPath, string type, string url) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
try {
|
||||
var buffer = new WebClient().DownloadData(url);
|
||||
|
@ -178,6 +178,7 @@
|
||||
<Compile Include="Providers\OEmbedMenu.cs" />
|
||||
<Compile Include="Providers\WebSearchMenu.cs" />
|
||||
<Compile Include="ResourceManifest.cs" />
|
||||
<Compile Include="Security\MediaAuthorizationEventHandler.cs" />
|
||||
<Compile Include="Services\IMediaLibraryService.cs" />
|
||||
<Compile Include="Services\MediaLibraryService.cs" />
|
||||
<Compile Include="Services\Shapes.cs" />
|
||||
|
@ -4,13 +4,15 @@ using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.MediaLibrary {
|
||||
public class Permissions : IPermissionProvider {
|
||||
public static readonly Permission ManageMediaContent = new Permission { Description = "Managing Media", Name = "ManageMediaContent" };
|
||||
public static readonly Permission ManageMediaContent = new Permission { Description = "Manage Media", Name = "ManageMediaContent" };
|
||||
public static readonly Permission ManageOwnMedia = new Permission { Description = "Manage Own Media", Name = "ManageOwnMedia", ImpliedBy = new[] { ManageMediaContent } };
|
||||
|
||||
public virtual Feature Feature { get; set; }
|
||||
|
||||
public IEnumerable<Permission> GetPermissions() {
|
||||
return new[] {
|
||||
ManageMediaContent,
|
||||
ManageOwnMedia,
|
||||
};
|
||||
}
|
||||
|
||||
@ -33,6 +35,7 @@ namespace Orchard.MediaLibrary {
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Contributor",
|
||||
Permissions = new[] {ManageOwnMedia}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers {
|
||||
builder.AddImageSet("clientstorage")
|
||||
.Add(T("My Computer"), "5",
|
||||
menu => menu.Action("Index", "ClientStorage", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent));
|
||||
.Permission(Permissions.ManageOwnMedia));
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers {
|
||||
builder.AddImageSet("oembed")
|
||||
.Add(T("Media Url"), "10",
|
||||
menu => menu.Action("Index", "OEmbed", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent));
|
||||
.Permission(Permissions.ManageOwnMedia));
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers {
|
||||
builder.AddImageSet("websearch")
|
||||
.Add(T("Web Search"), "7",
|
||||
menu => menu.Action("Index", "WebSearch", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent));
|
||||
.Permission(Permissions.ManageOwnMedia));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.MediaLibrary.Models;
|
||||
using Orchard.MediaLibrary.Services;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.MediaLibrary.Security {
|
||||
public class MediaAuthorizationEventHandler : IAuthorizationServiceEventHandler {
|
||||
private readonly IAuthorizer _authorizer;
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
|
||||
public MediaAuthorizationEventHandler(
|
||||
IAuthorizer authorizer,
|
||||
IMediaLibraryService mediaLibraryService) {
|
||||
_authorizer = authorizer;
|
||||
_mediaLibraryService = mediaLibraryService;
|
||||
}
|
||||
|
||||
public void Checking(CheckAccessContext context) { }
|
||||
public void Complete(CheckAccessContext context) { }
|
||||
|
||||
public void Adjust(CheckAccessContext context) {
|
||||
var mediaPart = context.Content.As<MediaPart>();
|
||||
if (mediaPart != null) {
|
||||
if(_authorizer.Authorize(Permissions.ManageMediaContent)) {
|
||||
context.Granted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(_authorizer.Authorize(Permissions.ManageOwnMedia)) {
|
||||
context.Granted = _mediaLibraryService.CanManageMediaFolder(mediaPart.FolderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement;
|
||||
@ -36,7 +37,7 @@ namespace Orchard.MediaLibrary.Services {
|
||||
/// <returns>The public URL for the media.</returns>
|
||||
string GetMediaPublicUrl(string mediaPath, string fileName);
|
||||
|
||||
MediaFolder GetRootMediaFolder();
|
||||
IMediaFolder GetRootMediaFolder();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the media folders within a given relative path.
|
||||
@ -131,4 +132,30 @@ namespace Orchard.MediaLibrary.Services {
|
||||
/// <returns>The path to the uploaded file.</returns>
|
||||
string UploadMediaFile(string folderPath, string fileName, Stream inputStream);
|
||||
}
|
||||
|
||||
public static class MediaLibrayServiceExtensions {
|
||||
public static bool CanManageMediaFolder(this IMediaLibraryService service, string folderPath) {
|
||||
// The current user can manage a media if he has access to the whole hierarchy
|
||||
// or the media is under his personal storage folder.
|
||||
|
||||
var rootMediaFolder = service.GetRootMediaFolder();
|
||||
if (rootMediaFolder == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var mediaPath = folderPath + "\\";
|
||||
var rootPath = rootMediaFolder.MediaPath + "\\";
|
||||
|
||||
return mediaPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static string GetRootedFolderPath(this IMediaLibraryService service, string folderPath) {
|
||||
var rootMediaFolder = service.GetRootMediaFolder();
|
||||
if (rootMediaFolder != null) {
|
||||
return Path.Combine(rootMediaFolder.MediaPath, folderPath ?? "");
|
||||
}
|
||||
|
||||
return folderPath;
|
||||
}
|
||||
}
|
||||
}
|
@ -210,7 +210,21 @@ namespace Orchard.MediaLibrary.Services {
|
||||
return GetPublicUrl(Path.Combine(mediaPath, fileName));
|
||||
}
|
||||
|
||||
public MediaFolder GetRootMediaFolder() {
|
||||
public IMediaFolder GetRootMediaFolder() {
|
||||
if (_orchardServices.Authorizer.Authorize(Permissions.ManageMediaContent)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_orchardServices.Authorizer.Authorize(Permissions.ManageOwnMedia)) {
|
||||
var currentUser = _orchardServices.WorkContext.CurrentUser;
|
||||
var userPath = _storageProvider.Combine("Users", currentUser.UserName);
|
||||
|
||||
return new MediaFolder() {
|
||||
Name = currentUser.UserName,
|
||||
MediaPath = userPath
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace Orchard.MediaLibrary.Services {
|
||||
UrlHelper url) {
|
||||
|
||||
var user = _membershipService.ValidateUser(userName, password);
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMediaContent, user, null)) {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageOwnMedia, user, null)) {
|
||||
throw new OrchardCoreException(T("Access denied"));
|
||||
}
|
||||
|
||||
@ -72,6 +72,11 @@ namespace Orchard.MediaLibrary.Services {
|
||||
directoryName = "media";
|
||||
}
|
||||
|
||||
// If the user only has access to his own folder, rewrite the folder name
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMediaContent, user, null)) {
|
||||
directoryName = Path.Combine(_mediaLibraryService.GetRootedFolderPath(directoryName));
|
||||
}
|
||||
|
||||
try {
|
||||
// delete the file if it already exists, e.g. an updated image in a blog post
|
||||
// it's safe to delete the file as each content item gets a specific folder
|
||||
|
@ -112,7 +112,7 @@ var mediaLibrarySettings = {
|
||||
<div class="media-library-folder-title" data-bind="click: folderClicked, attr: { 'data-media-path': folderPath() }, css: {selected: isSelected()}">
|
||||
<a href="#" class="media-library-navigation-folder-link"><i data-bind=" css: {'icon-folder-open-alt': isExpanded(), 'icon-folder-close-alt': !isExpanded()}"></i><span data-bind=" text: name"></span></a>
|
||||
</div>
|
||||
<ul data-bind="template: { name: 'media-folder-template', foreach: childFolders, afterRender: afterRenderMediaFolderTemplate}, visible: isExpanded()">
|
||||
<ul data-bind="template: { name: 'media-folder-template', foreach: childFolders, afterRender: afterRenderMediaFolderTemplate}, visible: isExpanded()">
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
|
@ -6,10 +6,12 @@
|
||||
<div class="breadCrumbs">
|
||||
<p>@Html.ActionLink(T("Media Library").ToString(), "Index", "Admin", new { area = "Orchard.MediaLibrary" }, new {}) >
|
||||
@if (Model.FolderPath != null) {
|
||||
foreach (var folder in Model.FolderPath.Split('/')) {
|
||||
if (!String.IsNullOrEmpty(folder)) {
|
||||
@Html.ActionLink(folder, "Edit", new {folderPath = folder})
|
||||
<text>></text>
|
||||
var fullPath = "";
|
||||
foreach (var folder in Model.FolderPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar })) {
|
||||
if (!String.IsNullOrEmpty(folder)) {
|
||||
fullPath = Path.Combine(fullPath, folder);
|
||||
@Html.ActionLink(folder, "Index", "Admin", new {folderPath = fullPath }, null)
|
||||
<text>></text>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ namespace Orchard.Search.Controllers {
|
||||
// ignore search results which content item has been removed or unpublished
|
||||
var foundItems = _contentManager.GetMany<IContent>(foundIds, VersionOptions.Published, new QueryHints()).ToList();
|
||||
foreach (var contentItem in foundItems) {
|
||||
list.Add(_contentManager.BuildDisplay(contentItem, "Summary"));
|
||||
list.Add(_contentManager.BuildDisplay(contentItem, searchSettingPart.DisplayType));
|
||||
}
|
||||
searchHits.TotalItemCount -= foundIds.Count() - foundItems.Count();
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
@ -49,10 +47,13 @@ namespace Orchard.Search.Drivers {
|
||||
var model = new SearchSettingsFieldsViewModel();
|
||||
var searchFields = part.SearchFields;
|
||||
|
||||
model.DisplayType = part.DisplayType;
|
||||
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
part.SearchFields = model.Entries.ToDictionary(x => x.Index, x => x.Fields.Where(e => e.Selected).Select(e => e.Field).ToArray());
|
||||
part.FilterCulture = model.FilterCulture;
|
||||
part.DisplayType = model.DisplayType;
|
||||
}
|
||||
}
|
||||
else if (_indexManager.HasIndexProvider()) {
|
||||
|
@ -24,5 +24,10 @@ namespace Orchard.Search.Models {
|
||||
get { return this.Retrieve(x => x.SearchIndex); }
|
||||
set { this.Store(x => x.SearchIndex, value); }
|
||||
}
|
||||
|
||||
public string DisplayType {
|
||||
get { return this.Retrieve(x => x.DisplayType, "Summary"); }
|
||||
set { this.Store(x => x.DisplayType, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ namespace Orchard.Search.ViewModels {
|
||||
|
||||
public IList<IndexSettingsEntry> Entries { get; set; }
|
||||
public bool FilterCulture { get; set; }
|
||||
public string DisplayType { get; set; }
|
||||
}
|
||||
|
||||
public class IndexSettingsEntry {
|
||||
|
@ -44,5 +44,9 @@
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.FilterCulture)">@T("Narrow search to current culture only")</label>
|
||||
<span class="hint">@T("If checked, search results will only include content items localized in the current culture of the request.")</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.DisplayType)">@T("Display Type")</label>
|
||||
@Html.TextBoxFor(m => m.DisplayType, new { @class = "text single-line" })
|
||||
<span class="hint">@T("The display type to use for content items in the search results page.")</span>
|
||||
</div>
|
||||
</fieldset>
|
@ -1,17 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Taxonomies.Models;
|
||||
|
||||
namespace Orchard.Taxonomies.Services {
|
||||
public class TermCountProcessor : ITermCountProcessor {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly ITaxonomyService _taxonomyService;
|
||||
|
||||
public TermCountProcessor(IContentManager contentManager, ITaxonomyService taxonomyService) {
|
||||
_contentManager = contentManager;
|
||||
public TermCountProcessor(ITaxonomyService taxonomyService) {
|
||||
_taxonomyService = taxonomyService;
|
||||
}
|
||||
|
||||
@ -31,4 +25,4 @@ namespace Orchard.Taxonomies.Services {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,9 @@
|
||||
var selectedTerms = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Terms.Where(x => x.IsChecked).Select(x => new { label = x.Name, value = x.Id, levels = 0, disabled = true }));
|
||||
}
|
||||
<fieldset class="taxonomy-wrapper" data-name-prefix="@Html.FieldNameFor(m => m)" data-id-prefix="@Html.FieldIdFor(m => m)">
|
||||
<legend @if(Model.Settings.Required) { <text>class="required"</text> }>@Model.DisplayName</legend>
|
||||
<label @if(Model.Settings.Required) { <text>class="required"</text> }>@Model.DisplayName</label>
|
||||
@if (Model.Settings.Autocomplete) {
|
||||
<div class="terms-editor" data-all-terms="@allTerms" data-selected-terms="@selectedTerms" data-allow-new-terms="@Model.Settings.AllowCustomTerms.ToString().ToLower()" data-singlechoice="@Model.Settings.SingleChoice.ToString().ToLower()">
|
||||
<div class="terms-editor text text-medium" data-all-terms="@allTerms" data-selected-terms="@selectedTerms" data-allow-new-terms="@Model.Settings.AllowCustomTerms.ToString().ToLower()" data-singlechoice="@Model.Settings.SingleChoice.ToString().ToLower()">
|
||||
<ul></ul>
|
||||
@if (Model.Settings.SingleChoice) {
|
||||
<div class="hint">@T("Enter a single term. Hit <i>tab</i> or <i>enter</i> to apply the term.") @if (!Model.Settings.AllowCustomTerms) { <text>@T("This taxonomy does not allow you to create new terms.") </text> }</div>
|
||||
@ -67,7 +67,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@if (!Model.Terms.Any()) {
|
||||
@if (!Model.Terms.Any() && AuthorizedFor(Orchard.Taxonomies.Permissions.CreateTerm)) {
|
||||
<div class="no-terms">
|
||||
@T("There are no terms defined for {0} yet.", Model.DisplayName)
|
||||
<a href="@Url.Action("Index", "TermAdmin", new { taxonomyId = Model.TaxonomyId, area = "Orchard.Taxonomies" })">@T("Create some terms")</a>
|
||||
|
@ -42,7 +42,7 @@
|
||||
}
|
||||
</ul>
|
||||
|
||||
@if (!Model.Terms.Any()) {
|
||||
@if (!Model.Terms.Any() && AuthorizedFor(Orchard.Taxonomies.Permissions.CreateTerm)) {
|
||||
<div class="no-terms">
|
||||
@T("There are no terms defined for {0} yet.", Model.DisplayName)
|
||||
<a href="@Url.Action("Index", "TermAdmin", new { taxonomyId = Model.TaxonomyId, area = "Orchard.Taxonomies" })">@T("Create some terms")</a>
|
||||
|
@ -69,7 +69,8 @@ namespace Orchard.Widgets.Controllers {
|
||||
}
|
||||
|
||||
LayerPart currentLayer = layerId == null
|
||||
? layers.FirstOrDefault(layer => layer.Name == "Default") ?? layers.FirstOrDefault()
|
||||
// look for the "Default" layer, or take the first if it doesn't exist
|
||||
? layers.FirstOrDefault(x => x.Name == "Default") ?? layers.FirstOrDefault()
|
||||
: layers.FirstOrDefault(layer => layer.Id == layerId);
|
||||
|
||||
if (currentLayer == null && layerId != null) { // Incorrect layer id passed
|
||||
|
@ -68,7 +68,13 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
return confirm(confirmRemoveMessage);
|
||||
// use a custom message if its set in data-message
|
||||
var dataMessage = $(this).data('message');
|
||||
if (dataMessage === undefined) {
|
||||
dataMessage = confirmRemoveMessage;
|
||||
}
|
||||
|
||||
return confirm(dataMessage);
|
||||
});
|
||||
|
||||
$(".check-all").change(function () {
|
||||
|
@ -97,7 +97,7 @@
|
||||
@using (Script.Foot()) {
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var confirmRemoveMessage = '@T("Are you sure you want to remove this element ?")';
|
||||
var confirmRemoveMessage = '@T("Are you sure you want to remove this element?")';
|
||||
//]]>
|
||||
</script>
|
||||
}
|
@ -21,14 +21,6 @@ namespace Orchard.ContentManagement {
|
||||
|
||||
public virtual ContentItem ContentItem { get; set; }
|
||||
|
||||
//interesting thought, should/could parts also have zones (would then have zones on the page, content item and parts...)?
|
||||
private readonly IZoneCollection _zones = new ZoneCollection();
|
||||
public virtual IZoneCollection Zones {
|
||||
get {
|
||||
return _zones;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ContentItem's identifier.
|
||||
/// </summary>
|
||||
|
5
src/Orchard/DisplayManagement/IPositioned.cs
Normal file
5
src/Orchard/DisplayManagement/IPositioned.cs
Normal file
@ -0,0 +1,5 @@
|
||||
namespace Orchard.DisplayManagement {
|
||||
public interface IPositioned {
|
||||
string Position { get; }
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using Orchard.DisplayManagement.Shapes;
|
||||
using Orchard.DisplayManagement.Shapes;
|
||||
|
||||
namespace Orchard.DisplayManagement {
|
||||
/// <summary>
|
||||
|
26
src/Orchard/DisplayManagement/PositionWrapper.cs
Normal file
26
src/Orchard/DisplayManagement/PositionWrapper.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.DisplayManagement {
|
||||
public class PositionWrapper : IHtmlString, IPositioned {
|
||||
|
||||
private IHtmlString _value;
|
||||
public string Position { get; private set; }
|
||||
|
||||
public PositionWrapper(IHtmlString value, string position) {
|
||||
_value = value;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
public PositionWrapper(string value, string position)
|
||||
: this(new HtmlString(HttpUtility.HtmlEncode(value)), position) {
|
||||
}
|
||||
|
||||
public string ToHtmlString() {
|
||||
return _value.ToHtmlString();
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return _value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,11 +4,11 @@ using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.DisplayManagement.Shapes {
|
||||
[DebuggerTypeProxy(typeof(ShapeDebugView))]
|
||||
public class Shape : Composite, IShape, IEnumerable<object> {
|
||||
public class Shape : Composite, IShape, IPositioned, IEnumerable<object> {
|
||||
private const string DefaultPosition = "5";
|
||||
|
||||
private readonly IList<object> _items = new List<object>();
|
||||
@ -22,6 +22,12 @@ namespace Orchard.DisplayManagement.Shapes {
|
||||
public virtual IDictionary<string, string> Attributes { get { return _attributes; } }
|
||||
public virtual IEnumerable<dynamic> Items { get { return _items; } }
|
||||
|
||||
public string Position {
|
||||
get {
|
||||
return Metadata.Position;
|
||||
}
|
||||
}
|
||||
|
||||
public Shape() {
|
||||
Metadata = new ShapeMetadata();
|
||||
}
|
||||
@ -33,13 +39,14 @@ namespace Orchard.DisplayManagement.Shapes {
|
||||
}
|
||||
|
||||
try {
|
||||
// todo: (sebros) this is a temporary implementation to prevent common known scenarios throwing exceptions. The final solution would need to filter based on the fact that it is a Shape instance
|
||||
if (item is MvcHtmlString ||
|
||||
item is String) {
|
||||
// need to implement positioned wrapper for non-shape objects
|
||||
if (position != null && item is IHtmlString) {
|
||||
item = new PositionWrapper((IHtmlString)item, position);
|
||||
}
|
||||
else if (position != null && item is string) {
|
||||
item = new PositionWrapper((string)item, position);
|
||||
}
|
||||
else if (item is IShape) {
|
||||
((dynamic)item).Metadata.Position = position;
|
||||
((IShape)item).Metadata.Position = position;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
@ -151,6 +151,8 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BackgroundHttpContextFactory.cs" />
|
||||
<Compile Include="DisplayManagement\IPositioned.cs" />
|
||||
<Compile Include="DisplayManagement\PositionWrapper.cs" />
|
||||
<Compile Include="Data\Migration\Schema\AddUniqueConstraintCommand.cs" />
|
||||
<Compile Include="Data\Migration\Schema\DropUniqueConstraintCommand.cs" />
|
||||
<Compile Include="Environment\Extensions\Models\LifecycleStatus.cs" />
|
||||
|
@ -155,6 +155,10 @@ namespace Orchard.UI.Resources {
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the version of the resource.
|
||||
/// </summary>
|
||||
/// <param name="version">The version to set, in the form of <code>major.minor[.build[.revision]]</code></param>
|
||||
public ResourceDefinition SetVersion(string version) {
|
||||
Version = version;
|
||||
return this;
|
||||
|
Loading…
Reference in New Issue
Block a user