diff --git a/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs b/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs index 317e3dc8c..77dd7e36e 100644 --- a/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs +++ b/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs @@ -2,6 +2,7 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.Core.Common.Fields; +using Orchard.Core.Common.Models; using Orchard.Core.Common.Settings; namespace Orchard.Core.Common.Drivers { @@ -19,18 +20,14 @@ namespace Orchard.Core.Common.Drivers { } protected override DriverResult Display(ContentPart part, TextField field, string displayType) { - var locationSettings = - field.PartFieldDefinition.Settings.GetModel("DisplayLocation") ?? - new LocationSettings { Zone = "primary", Position = "5" }; + var locationSettings = field.PartFieldDefinition.Settings.GetModel().Get(displayType, "primary", "5"); return ContentFieldTemplate(field, TemplateName, GetPrefix(field, part)) .Location(locationSettings.Zone, locationSettings.Position); } protected override DriverResult Editor(ContentPart part, TextField field) { - var locationSettings = - field.PartFieldDefinition.Settings.GetModel("EditorLocation") ?? - new LocationSettings { Zone = "primary", Position = "5" }; + var locationSettings = field.PartFieldDefinition.Settings.GetModel().Get("Editor", "primary", "5"); return ContentFieldTemplate(field, TemplateName, GetPrefix(field, part)) .Location(locationSettings.Zone, locationSettings.Position); @@ -40,6 +37,5 @@ namespace Orchard.Core.Common.Drivers { updater.TryUpdateModel(field, GetPrefix(field, part), null, null); return Editor(part, field); } - } } diff --git a/src/Orchard.Web/Core/Common/Models/LocationDefinition.cs b/src/Orchard.Web/Core/Common/Models/LocationDefinition.cs new file mode 100644 index 000000000..7d5274924 --- /dev/null +++ b/src/Orchard.Web/Core/Common/Models/LocationDefinition.cs @@ -0,0 +1,8 @@ +using Orchard.Localization; + +namespace Orchard.Core.Common.Models { + public class LocationDefinition { + public string Name { get; set; } + public LocalizedString DisplayName { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Common/Models/LocationSettings.cs b/src/Orchard.Web/Core/Common/Models/LocationSettings.cs new file mode 100644 index 000000000..1e3058c0c --- /dev/null +++ b/src/Orchard.Web/Core/Common/Models/LocationSettings.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Orchard.ContentManagement.Drivers; + +namespace Orchard.Core.Common.Models { + public class LocationSettings : Dictionary { + public LocationSettings() { } + public LocationSettings(LocationSettings value) + : base(value) { + } + + public ContentLocation Get(string location) { + return Get(location, null, null); + } + + public ContentLocation Get(string location, string defaultZone, string defaultPosition) { + ContentLocation result; + if (this.TryGetValue(location, out result)) { + return result; + } + return new ContentLocation { Zone = defaultZone, Position = defaultPosition }; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Common/Settings/LocationSettingsEditorEvents.cs b/src/Orchard.Web/Core/Common/Settings/LocationSettingsEditorEvents.cs index dda784b98..325b3855b 100644 --- a/src/Orchard.Web/Core/Common/Settings/LocationSettingsEditorEvents.cs +++ b/src/Orchard.Web/Core/Common/Settings/LocationSettingsEditorEvents.cs @@ -4,58 +4,110 @@ using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.ViewModels; +using Orchard.Core.Common.Models; +using Orchard.Localization; namespace Orchard.Core.Common.Settings { public class LocationSettingsEditorEvents : ContentDefinitionEditorEventsBase { - public override IEnumerable TypePartEditor(ContentTypeDefinition.Part definition) { - yield return TypePartEditorForLocation(definition, "DisplayLocation"); - yield return TypePartEditorForLocation(definition, "EditorLocation"); + public LocationSettingsEditorEvents() { + T = NullLocalizer.Instance; } - private TemplateViewModel TypePartEditorForLocation(ContentTypeDefinition.Part definition, string locationSettings) { + public Localizer T { get; set; } + + private IEnumerable GetPredefinedLocations() { + yield return new LocationDefinition { Name = "Detail", DisplayName = T("Location in a \"Detail\" screen") }; + yield return new LocationDefinition { Name = "Editor", DisplayName = T("Location in a \"Editor\" screen") }; + yield return new LocationDefinition { Name = "Summary", DisplayName = T("Location in a \"Summary\" screen (Front-end)") }; + yield return new LocationDefinition { Name = "SummaryAdmin", DisplayName = T("Location in a \"Summary\" screen (Admin)") }; + } + + private LocationSettings MergeSettings(LocationSettings partSettings, LocationSettings partDefinitionSettings) { + var result = new LocationSettings(partSettings); + foreach (var entry in partDefinitionSettings) { + if (!partSettings.ContainsKey(entry.Key)) + partSettings[entry.Key] = entry.Value; + } + return result; + } + + #region Standalone part definition + public override IEnumerable PartEditor(ContentPartDefinition definition) { + var settings = definition.Settings.GetModel(); + + foreach (var location in GetPredefinedLocations()) { + var viewModel = new LocationSettingsViewModel { + Definition = location, + Location = settings.Get(location.Name) + }; + yield return DefinitionTemplate(viewModel, templateName: "LocationSettings", prefix: location.Name); + } + } + + public override IEnumerable PartEditorUpdate(ContentPartDefinitionBuilder builder, IUpdateModel updateModel) { + var settings = new LocationSettings(); + foreach (var location in GetPredefinedLocations()) { + var viewModel = new LocationSettingsViewModel(); + updateModel.TryUpdateModel(viewModel, location.Name, null, null); + settings[location.Name] = viewModel.Location; + yield return DefinitionTemplate(viewModel, templateName: "LocationSettings", prefix: location.Name); + } + builder.WithLocation(settings); + } + #endregion + + #region Part in the context of a content type + public override IEnumerable TypePartEditor(ContentTypeDefinition.Part definition) { // Look for the setting in the most specific settings first (part definition in type) // then in the global part definition. - var settings = - definition.Settings.TryGetModel(locationSettings) ?? - definition.PartDefinition.Settings.GetModel(locationSettings); + var partSettings = definition.Settings.GetModel(); + var partDefinitionSettings = definition.PartDefinition.Settings.GetModel(); + var settings = MergeSettings(partSettings, partDefinitionSettings); - return DefinitionTemplate(settings, locationSettings, locationSettings); + foreach (var location in GetPredefinedLocations()) { + var viewModel = new LocationSettingsViewModel { + Definition = location, + Location = settings.Get(location.Name) + }; + yield return DefinitionTemplate(viewModel, templateName: "LocationSettings", prefix: location.Name); + } } public override IEnumerable TypePartEditorUpdate(ContentTypeDefinitionBuilder.PartConfigurer builder, IUpdateModel updateModel) { - yield return TypePartEditorUpdateForLocation(builder, updateModel, "DisplayLocation"); - yield return TypePartEditorUpdateForLocation(builder, updateModel, "EditorLocation"); - } - - private TemplateViewModel TypePartEditorUpdateForLocation(ContentTypeDefinitionBuilder.PartConfigurer builder, IUpdateModel updateModel, string locationSettings) { - var locationsettings = new LocationSettings(); - updateModel.TryUpdateModel(locationsettings, locationSettings, null, null); - builder.WithLocation("EditorLocation", locationsettings.Zone, locationsettings.Position); - return DefinitionTemplate(locationsettings, locationSettings, locationSettings); + var settings = new LocationSettings(); + foreach (var location in GetPredefinedLocations()) { + var viewModel = new LocationSettingsViewModel(); + updateModel.TryUpdateModel(viewModel, location.Name, null, null); + settings[location.Name] = viewModel.Location; + yield return DefinitionTemplate(viewModel, templateName: "LocationSettings", prefix: location.Name); + } + builder.WithLocation(settings); } + #endregion + #region Field within a content part public override IEnumerable PartFieldEditor(ContentPartDefinition.Field definition) { - yield return PartFieldEditorForLocation(definition, "DisplayLocation"); - yield return PartFieldEditorForLocation(definition, "EditorLocation"); + var settings = definition.Settings.GetModel(); + foreach (var location in GetPredefinedLocations()) { + var viewModel = new LocationSettingsViewModel { + Definition = location, + Location = settings.Get(location.Name) + }; + yield return DefinitionTemplate(viewModel, templateName: "LocationSettings", prefix: location.Name); + } } - private TemplateViewModel PartFieldEditorForLocation(ContentPartDefinition.Field definition, string locationSettings) { - var settings = definition.Settings.GetModel(locationSettings); - return DefinitionTemplate(settings, locationSettings, locationSettings); - } - - public override IEnumerable PartFieldEditorUpdate(ContentPartDefinitionBuilder.FieldConfigurer builder, IUpdateModel updateModel) { - yield return PartFieldEditorUpdateForLocation(builder, updateModel, "DisplayLocation"); - yield return PartFieldEditorUpdateForLocation(builder, updateModel, "EditorLocation"); - } - - private TemplateViewModel PartFieldEditorUpdateForLocation(ContentPartDefinitionBuilder.FieldConfigurer builder, IUpdateModel updateModel, string locationSettings) { - var model = new LocationSettings(); - updateModel.TryUpdateModel(model, locationSettings, null, null); - builder.WithLocation(locationSettings, model.Zone, model.Position); - return DefinitionTemplate(model); + var settings = new LocationSettings(); + foreach (var location in GetPredefinedLocations()) { + var viewModel = new LocationSettingsViewModel(); + updateModel.TryUpdateModel(viewModel, location.Name, null, null); + settings[location.Name] = viewModel.Location; + yield return DefinitionTemplate(viewModel, templateName: "LocationSettings", prefix: location.Name); + } + builder.WithLocation(settings); } + #endregion } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Common/ViewModels/LocationSettingsViewModel.cs b/src/Orchard.Web/Core/Common/ViewModels/LocationSettingsViewModel.cs new file mode 100644 index 000000000..11dc57e13 --- /dev/null +++ b/src/Orchard.Web/Core/Common/ViewModels/LocationSettingsViewModel.cs @@ -0,0 +1,9 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.Core.Common.Models; + +namespace Orchard.Core.Common.Settings { + public class LocationSettingsViewModel { + public LocationDefinition Definition { get; set; } + public ContentLocation Location { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/DisplayLocation.ascx b/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/DisplayLocation.ascx deleted file mode 100644 index bc1255ebc..000000000 --- a/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/DisplayLocation.ascx +++ /dev/null @@ -1,12 +0,0 @@ -<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> -
- <%:T("Display location") %> - - - <%:Html.EditorFor(m=>m.Zone) %> - <%:Html.ValidationMessageFor(m => m.Zone)%> - - - <%:Html.EditorFor(m=>m.Position) %> - <%:Html.ValidationMessageFor(m => m.Position)%> -
diff --git a/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/EditorLocation.ascx b/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/EditorLocation.ascx deleted file mode 100644 index 858c16d1c..000000000 --- a/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/EditorLocation.ascx +++ /dev/null @@ -1,12 +0,0 @@ -<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> -
- <%:T("Editor Location") %> - - - <%:Html.EditorFor(m=>m.Zone) %> - <%:Html.ValidationMessageFor(m => m.Zone)%> - - - <%:Html.EditorFor(m=>m.Position) %> - <%:Html.ValidationMessageFor(m => m.Position)%> -
diff --git a/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/LocationSettings.ascx b/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/LocationSettings.ascx new file mode 100644 index 000000000..bcda2b218 --- /dev/null +++ b/src/Orchard.Web/Core/Common/Views/DefinitionTemplates/LocationSettings.ascx @@ -0,0 +1,12 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +
+ <%:T("{0}", Model.Definition.DisplayName) %> + + + <%:Html.EditorFor(m => m.Location.Zone)%> + <%:Html.ValidationMessageFor(m => m.Location.Zone)%> + + + <%:Html.EditorFor(m => m.Location.Position)%> + <%:Html.ValidationMessageFor(m => m.Location.Position)%> +
diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index 0fdb0b1ca..bbf80b552 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -67,11 +67,13 @@ + + - + @@ -226,8 +228,7 @@ - - + diff --git a/src/Orchard.Web/Core/Routable/DataMigrations/RoutableDataMigration.cs b/src/Orchard.Web/Core/Routable/DataMigrations/RoutableDataMigration.cs index 256951bac..e46164c1a 100644 --- a/src/Orchard.Web/Core/Routable/DataMigrations/RoutableDataMigration.cs +++ b/src/Orchard.Web/Core/Routable/DataMigrations/RoutableDataMigration.cs @@ -1,4 +1,6 @@ -using Orchard.ContentManagement.MetaData; +using System.Collections.Generic; +using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; using Orchard.Core.Routable.Models; using Orchard.Data.Migration; @@ -20,7 +22,9 @@ namespace Orchard.Core.Routable.DataMigrations { public int UpdateFrom1() { ContentDefinitionManager.AlterPartDefinition(typeof(IsRoutable).Name, cfg => cfg - .WithLocation("EditorLocation", "primary", "before.5")); + .WithLocation(new Dictionary { + {"Editor", new ContentLocation { Zone = "primary", Position = "before.5" }} + } )); return 2; } diff --git a/src/Orchard.Web/Core/Routable/Drivers/RoutableDriver.cs b/src/Orchard.Web/Core/Routable/Drivers/RoutableDriver.cs index 203a5324f..612ef2af0 100644 --- a/src/Orchard.Web/Core/Routable/Drivers/RoutableDriver.cs +++ b/src/Orchard.Web/Core/Routable/Drivers/RoutableDriver.cs @@ -1,6 +1,7 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Aspects; using Orchard.ContentManagement.Drivers; +using Orchard.Core.Common.Models; using Orchard.Core.Common.Settings; using Orchard.Core.Routable.Models; using Orchard.Core.Routable.Services; @@ -67,8 +68,8 @@ namespace Orchard.Core.Routable.Drivers { : ""; } - var locationSettings = part.PartDefinition.Settings.GetModel("EditorLocation"); - return ContentPartTemplate(model, TemplateName, Prefix).Location(locationSettings.Zone, locationSettings.Position); + var location = part.PartDefinition.Settings.GetModel().Get("Editor"); + return ContentPartTemplate(model, TemplateName, Prefix).Location(location.Zone, location.Position); } protected override DriverResult Editor(IsRoutable part, IUpdateModel updater) { diff --git a/src/Orchard/ContentManagement/Drivers/ContentLocation.cs b/src/Orchard/ContentManagement/Drivers/ContentLocation.cs new file mode 100644 index 000000000..e2b5cc304 --- /dev/null +++ b/src/Orchard/ContentManagement/Drivers/ContentLocation.cs @@ -0,0 +1,6 @@ +namespace Orchard.ContentManagement.Drivers { + public class ContentLocation { + public string Zone { get; set; } + public string Position { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs b/src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs index 50c00266f..f8419c98d 100644 --- a/src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs +++ b/src/Orchard/ContentManagement/MetaData/Builders/ContentPartDefinitionBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.MetaData.Models; namespace Orchard.ContentManagement.MetaData.Builders { @@ -114,35 +115,38 @@ namespace Orchard.ContentManagement.MetaData.Builders { } public static class ContentPartDefinitionBuilderExtensions { + public static IEnumerable> GetSettingEntries(IDictionary locationSettings) { + int index = 0; + foreach (var entry in locationSettings) { + var zone = string.IsNullOrEmpty(entry.Value.Zone) ? null : entry.Value.Zone; + var position = string.IsNullOrEmpty(entry.Value.Position) ? null : entry.Value.Position; + var locationName = (zone == null && position == null) ? null : entry.Key; - public static ContentPartDefinitionBuilder WithLocation(this ContentPartDefinitionBuilder obj, string location, string zone, string position) { - if (string.IsNullOrEmpty(zone)) - zone = null; - if (string.IsNullOrEmpty(position)) - position = null; - return obj - .WithSetting(string.Format("{0}.Zone", location), zone) - .WithSetting(string.Format("{0}.Position", location), position); + var prefix = string.Format("LocationSettings[{0}]", index); + yield return new KeyValuePair(string.Format("{0}.Key", prefix), locationName); + yield return new KeyValuePair(string.Format("{0}.Value.Zone", prefix), zone); + yield return new KeyValuePair(string.Format("{0}.Value.Position", prefix), position); + + index++; + } } - public static ContentTypeDefinitionBuilder.PartConfigurer WithLocation(this ContentTypeDefinitionBuilder.PartConfigurer obj, string location, string zone, string position) { - if (string.IsNullOrEmpty(zone)) - zone = null; - if (string.IsNullOrEmpty(position)) - position = null; - return obj - .WithSetting(string.Format("{0}.Zone", location), zone) - .WithSetting(string.Format("{0}.Position", location), position); + public static ContentPartDefinitionBuilder WithLocation(this ContentPartDefinitionBuilder obj, IDictionary settings) { + foreach (var entry in GetSettingEntries(settings)) + obj = obj.WithSetting(entry.Key, entry.Value); + return obj; } - public static ContentPartDefinitionBuilder.FieldConfigurer WithLocation(this ContentPartDefinitionBuilder.FieldConfigurer obj, string location, string zone, string position) { - if (string.IsNullOrEmpty(zone)) - zone = null; - if (string.IsNullOrEmpty(position)) - position = null; - return obj - .WithSetting(string.Format("{0}.Zone", location), zone) - .WithSetting(string.Format("{0}.Position", location), position); + public static ContentTypeDefinitionBuilder.PartConfigurer WithLocation(this ContentTypeDefinitionBuilder.PartConfigurer obj, IDictionary settings) { + foreach (var entry in GetSettingEntries(settings)) + obj = obj.WithSetting(entry.Key, entry.Value); + return obj; + } + + public static ContentPartDefinitionBuilder.FieldConfigurer WithLocation(this ContentPartDefinitionBuilder.FieldConfigurer obj, IDictionary settings) { + foreach (var entry in GetSettingEntries(settings)) + obj = obj.WithSetting(entry.Key, entry.Value); + return obj; } } } \ No newline at end of file diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 130394e40..51fdc1e9b 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -197,6 +197,7 @@ Code +