mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-24 01:49:12 +08:00
Updates the placement editor screen to support moving shapes into tabs (#7795)
Fixes #7791
This commit is contained in:
committed by
Sébastien Ros
parent
7373c11a1e
commit
af922a01be
@@ -28,8 +28,8 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
private readonly ShellSettings _settings;
|
private readonly ShellSettings _settings;
|
||||||
|
|
||||||
public AdminController(
|
public AdminController(
|
||||||
IOrchardServices orchardServices,
|
IOrchardServices orchardServices,
|
||||||
IContentDefinitionService contentDefinitionService,
|
IContentDefinitionService contentDefinitionService,
|
||||||
IContentDefinitionManager contentDefinitionManager,
|
IContentDefinitionManager contentDefinitionManager,
|
||||||
IPlacementService placementService,
|
IPlacementService placementService,
|
||||||
Lazy<IEnumerable<IShellSettingsManagerEventHandler>> settingsManagerEventHandlers,
|
Lazy<IEnumerable<IShellSettingsManagerEventHandler>> settingsManagerEventHandlers,
|
||||||
@@ -101,7 +101,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var contentTypeDefinition = _contentDefinitionService.AddType(viewModel.Name, viewModel.DisplayName);
|
var contentTypeDefinition = _contentDefinitionService.AddType(viewModel.Name, viewModel.DisplayName);
|
||||||
|
|
||||||
// adds CommonPart by default
|
// adds CommonPart by default
|
||||||
_contentDefinitionService.AddPartToType("CommonPart", viewModel.Name);
|
_contentDefinitionService.AddPartToType("CommonPart", viewModel.Name);
|
||||||
|
|
||||||
@@ -148,9 +148,21 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
if (contentTypeDefinition == null)
|
if (contentTypeDefinition == null)
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
|
|
||||||
|
var grouped = _placementService.GetEditorPlacement(id)
|
||||||
|
.OrderBy(x => x.PlacementInfo.GetPosition(), new FlatPositionComparer())
|
||||||
|
.ThenBy(x => x.PlacementSettings.ShapeType)
|
||||||
|
.Where(e => e.PlacementSettings.Zone == "Content")
|
||||||
|
.GroupBy(x => x.PlacementInfo.GetTab())
|
||||||
|
.ToDictionary(x => x.Key, y => y.ToList());
|
||||||
|
|
||||||
|
var content = grouped.ContainsKey("") ? grouped[""] : new List<DriverResultPlacement>();
|
||||||
|
var listPlacements = grouped.Values.SelectMany(e => e).ToList();
|
||||||
|
|
||||||
|
grouped.Remove("");
|
||||||
var placementModel = new EditPlacementViewModel {
|
var placementModel = new EditPlacementViewModel {
|
||||||
PlacementSettings = contentTypeDefinition.GetPlacement(PlacementType.Editor),
|
Content = content,
|
||||||
AllPlacements = _placementService.GetEditorPlacement(id).OrderBy(x => x.PlacementSettings.Position, new FlatPositionComparer()).ThenBy(x => x.PlacementSettings.ShapeType).ToList(),
|
AllPlacements = listPlacements,
|
||||||
|
Tabs = grouped,
|
||||||
ContentTypeDefinition = contentTypeDefinition,
|
ContentTypeDefinition = contentTypeDefinition,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -168,20 +180,10 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
if (contentTypeDefinition == null)
|
if (contentTypeDefinition == null)
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
|
|
||||||
var allPlacements = _placementService.GetEditorPlacement(id).ToList();
|
|
||||||
var result = new List<PlacementSettings>(contentTypeDefinition.GetPlacement(PlacementType.Editor));
|
|
||||||
|
|
||||||
contentTypeDefinition.ResetPlacement(PlacementType.Editor);
|
contentTypeDefinition.ResetPlacement(PlacementType.Editor);
|
||||||
|
|
||||||
foreach(var driverPlacement in viewModel.AllPlacements) {
|
foreach (var placement in viewModel.AllPlacements) {
|
||||||
// if the placement has changed, persist it
|
var placementSetting = placement.PlacementSettings;
|
||||||
if (!allPlacements.Any(x => x.PlacementSettings.Equals(driverPlacement.PlacementSettings))) {
|
|
||||||
result = result.Where(x => !x.IsSameAs(driverPlacement.PlacementSettings)).ToList();
|
|
||||||
result.Add(driverPlacement.PlacementSettings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(var placementSetting in result) {
|
|
||||||
contentTypeDefinition.Placement(PlacementType.Editor,
|
contentTypeDefinition.Placement(PlacementType.Editor,
|
||||||
placementSetting.ShapeType,
|
placementSetting.ShapeType,
|
||||||
placementSetting.Differentiator,
|
placementSetting.Differentiator,
|
||||||
@@ -195,7 +197,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
|
|
||||||
_settingsManagerEventHandlers.Value.Invoke(x => x.Saved(_settings), Logger);
|
_settingsManagerEventHandlers.Value.Invoke(x => x.Saved(_settings), Logger);
|
||||||
|
|
||||||
return RedirectToAction("EditPlacement", new {id});
|
return RedirectToAction("EditPlacement", new { id });
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost, ActionName("EditPlacement")]
|
[HttpPost, ActionName("EditPlacement")]
|
||||||
@@ -234,11 +236,11 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
TryUpdateModel(edited);
|
TryUpdateModel(edited);
|
||||||
typeViewModel.DisplayName = edited.DisplayName ?? string.Empty;
|
typeViewModel.DisplayName = edited.DisplayName ?? string.Empty;
|
||||||
|
|
||||||
if ( String.IsNullOrWhiteSpace(typeViewModel.DisplayName) ) {
|
if (String.IsNullOrWhiteSpace(typeViewModel.DisplayName)) {
|
||||||
ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString());
|
ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), typeViewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase) && !String.Equals(t.Name, id)) ) {
|
if (_contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), typeViewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase) && !String.Equals(t.Name, id))) {
|
||||||
ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString());
|
ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +273,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
_contentDefinitionService.RemoveType(id, true);
|
_contentDefinitionService.RemoveType(id, true);
|
||||||
|
|
||||||
Services.Notifier.Success(T("\"{0}\" has been removed.", typeViewModel.DisplayName));
|
Services.Notifier.Success(T("\"{0}\" has been removed.", typeViewModel.DisplayName));
|
||||||
|
|
||||||
return RedirectToAction("List");
|
return RedirectToAction("List");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +324,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
return AddPartsTo(id);
|
return AddPartsTo(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RedirectToAction("Edit", new {id});
|
return RedirectToAction("Edit", new { id });
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult RemovePartFrom(string id) {
|
public ActionResult RemovePartFrom(string id) {
|
||||||
@@ -364,7 +366,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
|
|
||||||
Services.Notifier.Success(T("The \"{0}\" part has been removed.", viewModel.Name));
|
Services.Notifier.Success(T("The \"{0}\" part has been removed.", viewModel.Name));
|
||||||
|
|
||||||
return RedirectToAction("Edit", new {id});
|
return RedirectToAction("Edit", new { id });
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -447,8 +449,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
|
|
||||||
[HttpPost, ActionName("EditPart")]
|
[HttpPost, ActionName("EditPart")]
|
||||||
[FormValueRequired("submit.Delete")]
|
[FormValueRequired("submit.Delete")]
|
||||||
public ActionResult DeletePart(string id)
|
public ActionResult DeletePart(string id) {
|
||||||
{
|
|
||||||
if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to delete a content part.")))
|
if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to delete a content part.")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
@@ -497,8 +498,8 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
if (partViewModel == null) {
|
if (partViewModel == null) {
|
||||||
// id passed in might be that of a type w/ no implicit field
|
// id passed in might be that of a type w/ no implicit field
|
||||||
if (typeViewModel != null) {
|
if (typeViewModel != null) {
|
||||||
partViewModel = new EditPartViewModel {Name = typeViewModel.Name};
|
partViewModel = new EditPartViewModel { Name = typeViewModel.Name };
|
||||||
_contentDefinitionService.AddPart(new CreatePartViewModel {Name = partViewModel.Name});
|
_contentDefinitionService.AddPart(new CreatePartViewModel { Name = partViewModel.Name });
|
||||||
_contentDefinitionService.AddPartToType(partViewModel.Name, typeViewModel.Name);
|
_contentDefinitionService.AddPartToType(partViewModel.Name, typeViewModel.Name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -555,7 +556,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
Services.Notifier.Success(T("The \"{0}\" field has been added.", viewModel.DisplayName));
|
Services.Notifier.Success(T("The \"{0}\" field has been added.", viewModel.DisplayName));
|
||||||
|
|
||||||
if (typeViewModel != null) {
|
if (typeViewModel != null) {
|
||||||
return RedirectToAction("Edit", new {id});
|
return RedirectToAction("Edit", new { id });
|
||||||
}
|
}
|
||||||
|
|
||||||
return RedirectToAction("EditPart", new { id });
|
return RedirectToAction("EditPart", new { id });
|
||||||
@@ -573,7 +574,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
|
|
||||||
var fieldViewModel = partViewModel.Fields.FirstOrDefault(x => x.Name == name);
|
var fieldViewModel = partViewModel.Fields.FirstOrDefault(x => x.Name == name);
|
||||||
|
|
||||||
if(fieldViewModel == null) {
|
if (fieldViewModel == null) {
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,14 +603,14 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
|
|
||||||
// prevent null reference exception in validation
|
// prevent null reference exception in validation
|
||||||
viewModel.DisplayName = viewModel.DisplayName ?? String.Empty;
|
viewModel.DisplayName = viewModel.DisplayName ?? String.Empty;
|
||||||
|
|
||||||
// remove extra spaces
|
// remove extra spaces
|
||||||
viewModel.DisplayName = viewModel.DisplayName.Trim();
|
viewModel.DisplayName = viewModel.DisplayName.Trim();
|
||||||
|
|
||||||
if (String.IsNullOrWhiteSpace(viewModel.DisplayName)) {
|
if (String.IsNullOrWhiteSpace(viewModel.DisplayName)) {
|
||||||
ModelState.AddModelError("DisplayName", T("The Display Name name can't be empty.").ToString());
|
ModelState.AddModelError("DisplayName", T("The Display Name name can't be empty.").ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_contentDefinitionService.GetPart(partViewModel.Name).Fields.Any(t => t.Name != viewModel.Name && String.Equals(t.DisplayName.Trim(), viewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase))) {
|
if (_contentDefinitionService.GetPart(partViewModel.Name).Fields.Any(t => t.Name != viewModel.Name && String.Equals(t.DisplayName.Trim(), viewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase))) {
|
||||||
ModelState.AddModelError("DisplayName", T("A field with the same Display Name already exists.").ToString());
|
ModelState.AddModelError("DisplayName", T("A field with the same Display Name already exists.").ToString());
|
||||||
}
|
}
|
||||||
@@ -620,7 +621,7 @@ namespace Orchard.ContentTypes.Controllers {
|
|||||||
|
|
||||||
var field = _contentDefinitionManager.GetPartDefinition(id).Fields.FirstOrDefault(x => x.Name == viewModel.Name);
|
var field = _contentDefinitionManager.GetPartDefinition(id).Fields.FirstOrDefault(x => x.Name == viewModel.Name);
|
||||||
|
|
||||||
if(field == null) {
|
if (field == null) {
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Module.txt" />
|
<Content Include="Module.txt" />
|
||||||
<Content Include="Scripts\admin-contenttypes.js" />
|
<Content Include="Scripts\admin-contenttypes.js" />
|
||||||
|
<Content Include="Scripts\admin-placementeditor.js" />
|
||||||
<Content Include="Styles\Images\menu.contenttypes.png" />
|
<Content Include="Styles\Images\menu.contenttypes.png" />
|
||||||
<Content Include="Styles\Images\move.gif" />
|
<Content Include="Styles\Images\move.gif" />
|
||||||
<Content Include="Styles\menu.contenttypes-admin.css" />
|
<Content Include="Styles\menu.contenttypes-admin.css" />
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ namespace Orchard.ContentTypes {
|
|||||||
public class ResourceManifest : IResourceManifestProvider {
|
public class ResourceManifest : IResourceManifestProvider {
|
||||||
public void BuildManifests(ResourceManifestBuilder builder) {
|
public void BuildManifests(ResourceManifestBuilder builder) {
|
||||||
builder.Add().DefineStyle("ContentTypesAdmin").SetUrl("orchard-contenttypes-admin.css");
|
builder.Add().DefineStyle("ContentTypesAdmin").SetUrl("orchard-contenttypes-admin.css");
|
||||||
|
|
||||||
|
builder.Add().DefineScript("PlacementEditor")
|
||||||
|
.SetUrl("admin-placementeditor.js")
|
||||||
|
.SetDependencies("jQueryUI_Sortable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
(function ($) {
|
||||||
|
var assignPositions = function () {
|
||||||
|
var position = 0;
|
||||||
|
$('.type').each(function () {
|
||||||
|
var input = $(this);
|
||||||
|
var tab = input.closest(".zone-container").data("tab");
|
||||||
|
//input = input.next();
|
||||||
|
var postab = tab != "" ? position + "#" + tab : position + "";
|
||||||
|
reAssignIdName(input, position); // type
|
||||||
|
|
||||||
|
input = input.next();
|
||||||
|
reAssignIdName(input, position); // differentiator
|
||||||
|
|
||||||
|
input = input.next();
|
||||||
|
reAssignIdName(input, position); // zone
|
||||||
|
|
||||||
|
input = input.next();
|
||||||
|
reAssignIdName(input, position); // position
|
||||||
|
|
||||||
|
input.val(postab);
|
||||||
|
position++;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var reAssignIdName = function (input, pos) {
|
||||||
|
var name = input.attr('name');
|
||||||
|
input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + pos + ']'));
|
||||||
|
|
||||||
|
var id = input.attr('id');
|
||||||
|
input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + pos + '__'));
|
||||||
|
};
|
||||||
|
|
||||||
|
var startPos;
|
||||||
|
|
||||||
|
function initTab() {
|
||||||
|
$(".tabdrag").sortable({
|
||||||
|
placeholder: "placement-placeholder",
|
||||||
|
connectWith: ".tabdrag",
|
||||||
|
stop: function (event, ui) {
|
||||||
|
assignPositions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#sortableTabs').sortable({
|
||||||
|
placeholder: "tab-placeholder",
|
||||||
|
start: function (event, ui) {
|
||||||
|
var self = $(ui.item);
|
||||||
|
startPos = self.prevAll().size();
|
||||||
|
},
|
||||||
|
stop: function (event, ui) {
|
||||||
|
assignPositions();
|
||||||
|
$('#save-message').show();
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#newTab").click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// get the new tab name, cancel if blank
|
||||||
|
var tab = $("#tabName").val().replace(/\s/g, "");
|
||||||
|
if (!tab.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab.toLowerCase() === "content") {
|
||||||
|
$("#tabName").val("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// in tabs already
|
||||||
|
var tabs = getTabs(true);
|
||||||
|
if ($.inArray(tab, tabs) >= 0) {
|
||||||
|
$("#tabName").val("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#sortableTabs").append('<div data-tab="' + tab + '" class="zone-container tab-container"><h2><a class="delete">Delete</a>'
|
||||||
|
+ tab + '</h2><ul class="tabdrag"></ul></div>'
|
||||||
|
);
|
||||||
|
// make it sortable
|
||||||
|
initTab();
|
||||||
|
$("#sortableTabs").sortable("refresh");
|
||||||
|
// clear the textbox
|
||||||
|
$("#tabName").val("");
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove tabs
|
||||||
|
// append items to content, create content if not there
|
||||||
|
$("#placement").on("click", ".delete", function (e) {
|
||||||
|
var me = $(this);
|
||||||
|
var parent = me.parent(".zone-container");
|
||||||
|
var list = parent.children(".tabdrag").html();
|
||||||
|
// get first tab
|
||||||
|
var newList = $("#placement .tabdrag").first();
|
||||||
|
if (newList.length) {
|
||||||
|
parent.remove();
|
||||||
|
newList.append(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
assignPositions();
|
||||||
|
});
|
||||||
|
|
||||||
|
// toggle editor shapes
|
||||||
|
$("#placement").on("click", ".toggle", function (e) {
|
||||||
|
var $this = $(this);
|
||||||
|
var shape = $(this).next().next();
|
||||||
|
shape.toggle();
|
||||||
|
if ($this.text() == 'Show Editor Shape') {
|
||||||
|
$this.text('Hide Editor Shape');
|
||||||
|
} else {
|
||||||
|
$this.text('Show Editor Shape');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// returns all the tabs
|
||||||
|
function getTabs(header) {
|
||||||
|
var tabs = [];
|
||||||
|
$(".zone-container").each(function (index, e) {
|
||||||
|
tabs.push($(e).data("tab"));
|
||||||
|
});
|
||||||
|
|
||||||
|
return tabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
initTab();
|
||||||
|
assignPositions();
|
||||||
|
$('.shape-editor *').attr('disabled', 'disabled');
|
||||||
|
$("#placement").disableSelection();
|
||||||
|
})(jQuery);
|
||||||
@@ -18,6 +18,7 @@ using Orchard.UI.Zones;
|
|||||||
namespace Orchard.ContentTypes.Services {
|
namespace Orchard.ContentTypes.Services {
|
||||||
|
|
||||||
public class DriverResultPlacement {
|
public class DriverResultPlacement {
|
||||||
|
public PlacementInfo PlacementInfo { get; set; }
|
||||||
public PlacementSettings PlacementSettings { get; set; }
|
public PlacementSettings PlacementSettings { get; set; }
|
||||||
public DriverResult ShapeResult { get; set; }
|
public DriverResult ShapeResult { get; set; }
|
||||||
public dynamic Shape { get; set; }
|
public dynamic Shape { get; set; }
|
||||||
@@ -201,6 +202,7 @@ namespace Orchard.ContentTypes.Services {
|
|||||||
|
|
||||||
|
|
||||||
yield return new DriverResultPlacement {
|
yield return new DriverResultPlacement {
|
||||||
|
PlacementInfo = placement,
|
||||||
Shape = itemShape.Content,
|
Shape = itemShape.Content,
|
||||||
ShapeResult = contentShapeResult,
|
ShapeResult = contentShapeResult,
|
||||||
PlacementSettings = new PlacementSettings {
|
PlacementSettings = new PlacementSettings {
|
||||||
|
|||||||
@@ -21,38 +21,38 @@
|
|||||||
|
|
||||||
.manage-part, .manage-field {
|
.manage-part, .manage-field {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding:0;
|
padding: 0;
|
||||||
border-bottom: 1px solid #EAEAEA;
|
border-bottom: 1px solid #EAEAEA;
|
||||||
}
|
}
|
||||||
|
|
||||||
.manage-part h3,
|
.manage-part h3,
|
||||||
.manage-field h3 {
|
.manage-field h3 {
|
||||||
display: relative;
|
display: relative;
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.manage-part h3,
|
.manage-part h3,
|
||||||
.manage-field h3,
|
.manage-field h3,
|
||||||
.manage-part h4,
|
.manage-part h4,
|
||||||
.manage-type .manage-field .details,
|
.manage-type .manage-field .details,
|
||||||
.manage-type .manage-part .manage-field,
|
.manage-type .manage-part .manage-field,
|
||||||
.manage-type .manage-part .settings {
|
.manage-type .manage-part .settings {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.manage-part h3, .manage-field h3 {
|
.manage-part h3, .manage-field h3 {
|
||||||
margin: 1em 0 !important;
|
margin: 1em 0 !important;
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.manage-part .expando-glyph, .manage-field .expando-glyph {
|
.manage-part .expando-glyph, .manage-field .expando-glyph {
|
||||||
width:16px;
|
width: 16px;
|
||||||
height:16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.manage-type .manage-field .settings {
|
.manage-type .manage-field .settings {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
@@ -176,38 +176,81 @@ fieldset.action {
|
|||||||
|
|
||||||
|
|
||||||
/* PLACEMENT EDITOR */
|
/* PLACEMENT EDITOR */
|
||||||
|
.tabdrag {
|
||||||
#placement li {
|
min-height: 20px;
|
||||||
margin-bottom: 10px;
|
|
||||||
padding: 0px;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#placement li .shape-type {
|
.zone-container {
|
||||||
cursor: move;
|
border: 1px dotted #6F6F6F;
|
||||||
background-color: #eee;
|
padding: 10px;
|
||||||
background: #EEE url(images/move.gif) no-repeat 10px 15px;
|
margin-bottom: 10px;
|
||||||
height: 30px;
|
}
|
||||||
padding: 10px 0px 0px 30px;
|
|
||||||
|
.zone-container li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 0px;
|
||||||
|
border: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
#placement li .shape-editor {
|
#placement .zone-container h2 {
|
||||||
padding: 10px;
|
cursor: move;
|
||||||
background: white;
|
margin-top: 0px;
|
||||||
}
|
padding-left: 20px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#placement .tab-container {
|
||||||
|
background: white url(images/move.gif) no-repeat 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone-container li .shape-type {
|
||||||
|
cursor: move;
|
||||||
|
background-color: #eee;
|
||||||
|
background: #EEE url(images/move.gif) no-repeat 10px 10px;
|
||||||
|
height: 30px;
|
||||||
|
padding: 5px 0px 0px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#placement #content-tab {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone-container li .toggle {
|
||||||
|
float: right;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone-container li .shape-editor {
|
||||||
|
padding: 10px;
|
||||||
|
background: white;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#save-message {
|
#save-message {
|
||||||
display: none;
|
display: none;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#placement fieldset {
|
.zone-container fieldset {
|
||||||
float: inherit; /* prevent bad layout if float is defined to left in specific parts, e.g. datetimepicker */
|
float: inherit; /* prevent bad layout if float is defined to left in specific parts, e.g. datetimepicker */
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-placeholder {
|
||||||
|
background: #FDF5BC;
|
||||||
|
border: 1px solid #FDF5BC;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
.placement-placeholder {
|
.placement-placeholder {
|
||||||
background: #FDF5BC;
|
background: #FDF5BC;
|
||||||
border: 1px solid #FDF5BC;
|
border: 1px solid #FDF5BC;
|
||||||
height: 100px;
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zone-container .delete {
|
||||||
|
float: right;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ using Orchard.ContentTypes.Settings;
|
|||||||
namespace Orchard.ContentTypes.ViewModels {
|
namespace Orchard.ContentTypes.ViewModels {
|
||||||
public class EditPlacementViewModel {
|
public class EditPlacementViewModel {
|
||||||
public ContentTypeDefinition ContentTypeDefinition { get; set; }
|
public ContentTypeDefinition ContentTypeDefinition { get; set; }
|
||||||
public PlacementSettings[] PlacementSettings { get; set; }
|
|
||||||
public List<DriverResultPlacement> AllPlacements { get; set; }
|
public List<DriverResultPlacement> AllPlacements { get; set; }
|
||||||
|
public Dictionary<string, List<DriverResultPlacement>> Tabs { get; set; }
|
||||||
|
public List<DriverResultPlacement> Content { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,107 +1,71 @@
|
|||||||
|
@using Orchard.ContentTypes.Services
|
||||||
@model Orchard.ContentTypes.ViewModels.EditPlacementViewModel
|
@model Orchard.ContentTypes.ViewModels.EditPlacementViewModel
|
||||||
@{
|
@{
|
||||||
Style.Require("ContentTypesAdmin");
|
Style.Require("ContentTypesAdmin");
|
||||||
Script.Require("jQueryUI_Sortable");
|
Script.Require("PlacementEditor").AtFoot();
|
||||||
Layout.Title = T("Edit Placement - {0}", Model.ContentTypeDefinition.DisplayName).ToString();
|
Layout.Title = T("Edit Placement - {0}", Model.ContentTypeDefinition.DisplayName).ToString();
|
||||||
|
|
||||||
var hiddenShapes = Model.AllPlacements.Where(x => String.IsNullOrEmpty(x.PlacementSettings.Zone) && (String.IsNullOrWhiteSpace(x.PlacementSettings.Position) || x.PlacementSettings.Position == "-"));
|
int i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@helper RenderPlacement(DriverResultPlacement p, int i) {
|
||||||
|
var placement = p.PlacementSettings;
|
||||||
|
<li class="place" data-shape-type="@placement.ShapeType" data-shape-differentiator="@placement.Differentiator" data-shape-zone="Content" data-shape-position="@placement.Position">
|
||||||
|
<span class="toggle">Show Editor Shape</span>
|
||||||
|
<div class="shape-type"><h3>@placement.ShapeType @placement.Differentiator</h3></div>
|
||||||
|
<div class="shape-editor">
|
||||||
|
@try {
|
||||||
|
@Display(p.Shape)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.ShapeType, new { @class = "type" })
|
||||||
|
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Differentiator, new { @class = "differentiator" })
|
||||||
|
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Zone, new { @class = "zone" })
|
||||||
|
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Position, new { @class = "position" })
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div id="save-message" class="message message-Warning">@T("You need to hit \"Save\" in order to save your changes.")</div>
|
<div id="save-message" class="message message-Warning">@T("You need to hit \"Save\" in order to save your changes.")</div>
|
||||||
|
|
||||||
@using (Html.BeginFormAntiForgeryPost()) {
|
@using (Html.BeginFormAntiForgeryPost()) {
|
||||||
@Html.ValidationSummary()
|
@Html.ValidationSummary()
|
||||||
|
<div id="placement">
|
||||||
|
<div data-tab="" class="zone-container" id="content-tab">
|
||||||
|
<h2>Content</h2>
|
||||||
|
<ul class="tabdrag">
|
||||||
|
@foreach (var p in Model.Content) {
|
||||||
|
@RenderPlacement(p, i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="sortableTabs">
|
||||||
<ul id="placement">
|
@foreach (var tab in Model.Tabs) {
|
||||||
@for (int i = 0; i < Model.AllPlacements.Count; i++ ) {
|
<div data-tab="@tab.Key" class="zone-container tab-container">
|
||||||
|
<a class="delete">Delete</a>
|
||||||
var placement = Model.AllPlacements[i].PlacementSettings;
|
<h2>@tab.Key</h2>
|
||||||
|
<ul class="tabdrag">
|
||||||
if(placement.Zone != "Content") {
|
@foreach (var p in tab.Value) {
|
||||||
continue;
|
@RenderPlacement(p, i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
<li data-shape-type="@placement.ShapeType" data-shape-differentiator="@placement.Differentiator" data-shape-zone="Content" data-shape-position="@placement.Position">
|
</div>
|
||||||
<div class="shape-type"><h3>@placement.ShapeType @placement.Differentiator</h3></div>
|
|
||||||
<div class="shape-editor">
|
<div>
|
||||||
@try {
|
<input type="text" id="tabName" />
|
||||||
@Display(Model.AllPlacements[i].Shape)
|
<button class="primaryAction" id="newTab">@T("New Tab")</button>
|
||||||
}
|
</div>
|
||||||
catch {
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@* @shape.Position @(Model.PlacementSettings.Any(x => x.Equals(shape)))*@
|
|
||||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.ShapeType, new { @class = "type" })
|
|
||||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Differentiator, new { @class = "differentiator" })
|
|
||||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Zone, new { @class = "zone" })
|
|
||||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Position, new { @class = "position" })
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<fieldset class="action">
|
<fieldset class="action">
|
||||||
<button class="primaryAction" type="submit" name="submit.Save" value="Save">@T("Save")</button>
|
<button class="primaryAction" type="submit" name="submit.Save" value="Save">@T("Save")</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>
|
<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>
|
</fieldset>
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@using (Script.Foot()) {
|
|
||||||
<script type="text/javascript">
|
|
||||||
//<![CDATA[
|
|
||||||
(function ($) {
|
|
||||||
|
|
||||||
var assignPositions = function () {
|
|
||||||
var position = 0;
|
|
||||||
$('.type').each(function () {
|
|
||||||
var input = $(this);
|
|
||||||
reAssignIdName(input, position); // type
|
|
||||||
|
|
||||||
input = input.next();
|
|
||||||
reAssignIdName(input, position); // differentiator
|
|
||||||
|
|
||||||
input = input.next();
|
|
||||||
reAssignIdName(input, position); // zone
|
|
||||||
|
|
||||||
input = input.next();
|
|
||||||
reAssignIdName(input, position); // position
|
|
||||||
|
|
||||||
input.val(++position);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var reAssignIdName = function (input, pos) {
|
|
||||||
var name = input.attr('name');
|
|
||||||
input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + pos + ']'));
|
|
||||||
|
|
||||||
var id = input.attr('id');
|
|
||||||
input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + pos + '__'));
|
|
||||||
};
|
|
||||||
|
|
||||||
assignPositions();
|
|
||||||
|
|
||||||
var startPos;
|
|
||||||
|
|
||||||
$('#placement').sortable({
|
|
||||||
placeholder: "placement-placeholder",
|
|
||||||
start: function (event, ui) {
|
|
||||||
var self = $(ui.item);
|
|
||||||
startPos = self.prevAll().size();
|
|
||||||
},
|
|
||||||
stop: function (event, ui) {
|
|
||||||
assignPositions();
|
|
||||||
$('#save-message').show();
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.shape-editor *').attr('disabled', 'disabled');
|
|
||||||
|
|
||||||
$("#placement").disableSelection();
|
|
||||||
|
|
||||||
})(jQuery);
|
|
||||||
//]]>
|
|
||||||
</script>
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user