From f7e3f48df1b90e1e2078199d7aef6d6667d3a1b3 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 19 Nov 2015 17:39:52 +0100 Subject: [PATCH 1/3] Added support for configurable snippet elements. --- .../Helpers/SnippetHtmlExtensions.cs | 68 ++++++++++++ .../Models/SnippetDescriptor.cs | 11 ++ .../Models/SnippetFieldDescriptor.cs | 10 ++ .../Orchard.Layouts/Orchard.Layouts.csproj | 13 +++ .../Providers/SnippetElementHarvester.cs | 100 ++++++++++++++++-- .../CurrentThemeShapeBindingResolver.cs | 44 ++++++++ .../ICurrentThemeShapeBindingResolver.cs | 7 ++ .../Orchard.Layouts/Shapes/ElementShapes.cs | 24 +++-- .../ViewModels/SnippetFieldViewModel.cs | 8 ++ .../ViewModels/SnippetViewModel.cs | 13 +++ .../Elements.Snippet.Field.Text.cshtml | 11 ++ .../EditorTemplates/Elements.Snippet.cshtml | 10 ++ .../Views/Elements/Snippet.Design.cshtml | 11 +- .../Views/ButtonSnippet.cshtml | 10 ++ src/Orchard.Web/Themes/Themes.csproj | 8 ++ 15 files changed, 331 insertions(+), 17 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetDescriptor.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetFieldDescriptor.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/Services/CurrentThemeShapeBindingResolver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/Services/ICurrentThemeShapeBindingResolver.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetFieldViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.Field.Text.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.cshtml create mode 100644 src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs new file mode 100644 index 000000000..f863c0815 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs @@ -0,0 +1,68 @@ +using System; +using System.Web; +using System.Web.Mvc; +using Orchard.Layouts.Elements; +using Orchard.Layouts.Models; +using Orchard.Localization; + +namespace Orchard.Layouts.Helpers { + public static class SnippetHtmlExtensions { + + public static SnippetFieldDescriptorBuilder SnippetField(this HtmlHelper htmlHelper, string name, string type) { + var shape = (dynamic) htmlHelper.ViewData.Model; + + return new SnippetFieldDescriptorBuilder(shape) + .Named(name) + .WithType(type); + } + + public class SnippetFieldDescriptorBuilder : IHtmlString { + private readonly dynamic _shape; + + public SnippetFieldDescriptorBuilder(dynamic shape) { + _shape = shape; + Descriptor = new SnippetFieldDescriptor(); + } + + public SnippetFieldDescriptor Descriptor { get; private set; } + + public SnippetFieldDescriptorBuilder Named(string value) { + Descriptor.Name = value; + return this; + } + + public SnippetFieldDescriptorBuilder WithType(string value) { + Descriptor.Type = value; + return this; + } + + public SnippetFieldDescriptorBuilder WithDisplayName(LocalizedString value) { + Descriptor.DisplayName = value; + return this; + } + + public SnippetFieldDescriptorBuilder WithDescription(LocalizedString value) { + Descriptor.Description = value; + return this; + } + + public override string ToString() { + var registratorCallback = (Action)_shape.DescriptorRegistrationCallback; + + if (registratorCallback != null) + registratorCallback(Descriptor); + + var element = (Snippet)_shape.Element; + + if(element != null) + return element.Data.Get(Descriptor.Name); + + return null; + } + + public string ToHtmlString() { + return ToString(); + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetDescriptor.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetDescriptor.cs new file mode 100644 index 000000000..6a4c4332d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetDescriptor.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Orchard.Layouts.Models { + public class SnippetDescriptor { + public SnippetDescriptor() { + Fields = new List(); + } + + public IList Fields { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetFieldDescriptor.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetFieldDescriptor.cs new file mode 100644 index 000000000..7c5353303 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Models/SnippetFieldDescriptor.cs @@ -0,0 +1,10 @@ +using Orchard.Localization; + +namespace Orchard.Layouts.Models { + public class SnippetFieldDescriptor { + public string Type { get; set; } + public string Name { get; set; } + public LocalizedString DisplayName { get; set; } + public LocalizedString Description { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj b/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj index c379d3a19..c92e2059e 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Orchard.Layouts.csproj @@ -366,10 +366,17 @@ + + + + + + + @@ -608,6 +615,12 @@ + + + + + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs index ddcc556cc..3db58a023 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs @@ -8,10 +8,17 @@ using Orchard.Environment; using Orchard.Environment.Extensions; using Orchard.Layouts.Elements; using Orchard.Layouts.Framework.Display; +using Orchard.Layouts.Framework.Drivers; using Orchard.Layouts.Framework.Elements; using Orchard.Layouts.Framework.Harvesters; +using Orchard.Layouts.Helpers; +using Orchard.Layouts.Models; using Orchard.Layouts.Services; +using Orchard.Layouts.Shapes; +using Orchard.Layouts.ViewModels; +using Orchard.Localization; using Orchard.Themes.Services; +using Orchard.Tokens; using Orchard.Utility.Extensions; namespace Orchard.Layouts.Providers { @@ -22,18 +29,27 @@ namespace Orchard.Layouts.Providers { private readonly Work _siteThemeService; private readonly Work _shapeTableLocator; private readonly Work _elementFactory; + private readonly Work _shapeDisplay; + private readonly Work _currentThemeShapeBindingResolver; + private readonly Work _tokenizer; public SnippetElementHarvester( IWorkContextAccessor workContextAccessor, Work shapeFactory, Work siteThemeService, Work shapeTableLocator, - Work elementFactory) { + Work elementFactory, + Work shapeDisplay, + Work tokenizer, + Work currentThemeShapeBindingResolver) { _shapeFactory = shapeFactory; _siteThemeService = siteThemeService; _shapeTableLocator = shapeTableLocator; _elementFactory = elementFactory; + _shapeDisplay = shapeDisplay; + _tokenizer = tokenizer; + _currentThemeShapeBindingResolver = currentThemeShapeBindingResolver; workContextAccessor.GetContext(); } @@ -42,23 +58,71 @@ namespace Orchard.Layouts.Providers { var shapeTable = _shapeTableLocator.Value.Lookup(currentThemeName); var shapeDescriptors = shapeTable.Bindings.Where(x => !String.Equals(x.Key, "Elements_Snippet", StringComparison.OrdinalIgnoreCase) && x.Key.EndsWith(SnippetShapeSuffix, StringComparison.OrdinalIgnoreCase)).ToDictionary(x => x.Key, x => x.Value.ShapeDescriptor); var elementType = typeof (Snippet); - var snippetElement = _elementFactory.Value.Activate(elementType); + var snippetElement = (Snippet)_elementFactory.Value.Activate(elementType); foreach (var shapeDescriptor in shapeDescriptors) { var shapeType = shapeDescriptor.Value.ShapeType; + var snippetDescriptor = DescribeSnippet(shapeType, snippetElement); var elementName = GetDisplayName(shapeDescriptor.Value.BindingSource); var closureDescriptor = shapeDescriptor; yield return new ElementDescriptor(elementType, shapeType, T(elementName), T("An element that renders the {0} shape.", shapeType), snippetElement.Category) { - Displaying = displayContext => Displaying(displayContext, closureDescriptor.Value), - ToolboxIcon = "\uf10c" + Displaying = displayContext => Displaying(displayContext, closureDescriptor.Value, snippetDescriptor), + ToolboxIcon = "\uf10c", + EnableEditorDialog = snippetDescriptor.Fields.Any(), + Editor = ctx => Editor(snippetDescriptor, ctx), + UpdateEditor = ctx => UpdateEditor(snippetDescriptor, ctx) }; } } - private void Displaying(ElementDisplayingContext context, ShapeDescriptor shapeDescriptor) { + private void Editor(SnippetDescriptor descriptor, ElementEditorContext context) { + UpdateEditor(descriptor, context); + } + + private void UpdateEditor(SnippetDescriptor descriptor, ElementEditorContext context) { + var viewModel = new SnippetViewModel { + Descriptor = descriptor + }; + + if (context.Updater != null) { + foreach (var fieldDescriptor in descriptor.Fields) { + var name = fieldDescriptor.Name; + var result = context.ValueProvider.GetValue(name); + + if (result == null) + continue; + + context.Element.Data[name] = result.AttemptedValue; + } + } + + viewModel.FieldEditors = descriptor.Fields.Select(x => { + var fieldEditorTemplateName = String.Format("Elements.Snippet.Field.{0}", x.Type ?? "Text"); + var fieldDescriptorViewModel = new SnippetFieldViewModel { + Descriptor = x, + Value = context.Element.Data.Get(x.Name) + }; + var fieldEditor = context.ShapeFactory.EditorTemplate(TemplateName: fieldEditorTemplateName, Model: fieldDescriptorViewModel, Prefix: context.Prefix); + + return fieldEditor; + }).ToList(); + + var snippetEditorShape = context.ShapeFactory.EditorTemplate(TemplateName: "Elements.Snippet", Model: viewModel, Prefix: context.Prefix); + snippetEditorShape.Metadata.Position = "Fields:0"; + + context.EditorResult.Add(snippetEditorShape); + } + + private void Displaying(ElementDisplayingContext context, ShapeDescriptor shapeDescriptor, SnippetDescriptor snippetDescriptor) { var shapeType = shapeDescriptor.ShapeType; - var shape = _shapeFactory.Value.Create(shapeType); + var shape = (dynamic)_shapeFactory.Value.Create(shapeType); + + shape.Element = context.Element; + shape.SnippetDescriptor = snippetDescriptor; + + ElementShapes.AddTokenizers(shape, _tokenizer.Value); context.ElementShape.Snippet = shape; + context.ElementShape.SnippetDescriptor = snippetDescriptor; } private string GetDisplayName(string bindingSource) { @@ -66,5 +130,29 @@ namespace Orchard.Layouts.Providers { var lastIndex = fileName.IndexOf(SnippetShapeSuffix, StringComparison.OrdinalIgnoreCase); return fileName.Substring(0, lastIndex).CamelFriendly(); } + + private SnippetDescriptor DescribeSnippet(string shapeType, Snippet element) { + var shape = (dynamic)_shapeFactory.Value.Create(shapeType); + shape.Element = element; + return DescribeSnippet(shape); + } + + private SnippetDescriptor DescribeSnippet(dynamic shape) { + // Execute the shape and intercept calls to the Html.SnippetField method. + var descriptor = new SnippetDescriptor(); + shape.DescriptorRegistrationCallback = (Action) (fieldDescriptor => { + descriptor.Fields.Add(fieldDescriptor); + + if (fieldDescriptor.DisplayName == null) + fieldDescriptor.DisplayName = new LocalizedString(fieldDescriptor.Name); + }); + + using (_currentThemeShapeBindingResolver.Value.Enable()) { + _shapeDisplay.Value.Display(shape); + } + + shape.SnippetDescriptor = descriptor; + return descriptor; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Services/CurrentThemeShapeBindingResolver.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Services/CurrentThemeShapeBindingResolver.cs new file mode 100644 index 000000000..0746fd147 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Services/CurrentThemeShapeBindingResolver.cs @@ -0,0 +1,44 @@ +using System; +using Orchard.DisplayManagement; +using Orchard.DisplayManagement.Descriptors; +using Orchard.Environment.Extensions; +using Orchard.Layouts.Providers; +using Orchard.Themes.Services; + +namespace Orchard.Layouts.Services { + /// + /// Enables the rendering of shape templates from the admin while the shape templates reside in the current theme. + /// + [OrchardFeature("Orchard.Layouts.Snippets")] + public class CurrentThemeShapeBindingResolver : ICurrentThemeShapeBindingResolver, IShapeBindingResolver, IDisposable { + private readonly ISiteThemeService _siteThemeService; + private readonly IShapeTableLocator _shapeTableLocator; + + public CurrentThemeShapeBindingResolver(ISiteThemeService siteThemeService, IShapeTableLocator shapeTableLocator) { + _siteThemeService = siteThemeService; + _shapeTableLocator = shapeTableLocator; + } + + public bool Enabled { get; private set; } + + public bool TryGetDescriptorBinding(string shapeType, out ShapeBinding shapeBinding) { + shapeBinding = null; + + if (!Enabled) + return false; + + var currentThemeName = _siteThemeService.GetCurrentThemeName(); + var shapeTable = _shapeTableLocator.Lookup(currentThemeName); + return shapeTable.Bindings.TryGetValue(shapeType, out shapeBinding); + } + + public IDisposable Enable() { + Enabled = true; + return this; + } + + public void Dispose() { + Enabled = false; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ICurrentThemeShapeBindingResolver.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ICurrentThemeShapeBindingResolver.cs new file mode 100644 index 000000000..c216e3164 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ICurrentThemeShapeBindingResolver.cs @@ -0,0 +1,7 @@ +using System; + +namespace Orchard.Layouts.Services { + public interface ICurrentThemeShapeBindingResolver : IDependency { + IDisposable Enable(); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Shapes/ElementShapes.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Shapes/ElementShapes.cs index 9d60ee6e2..8a7b2294f 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Shapes/ElementShapes.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Shapes/ElementShapes.cs @@ -16,6 +16,19 @@ namespace Orchard.Layouts.Shapes { private readonly Work _shapeFactory; private readonly Work _tokenizer; + public static void AddTokenizers(dynamic elementShape, ITokenizer tokenizer) { + var element = (Element)elementShape.Element; + var content = (ContentItem)elementShape.ContentItem; + var htmlId = element.HtmlId; + var htmlClass = element.HtmlClass; + var htmlStyle = element.HtmlStyle; + + // Provide tokenizer functions. + elementShape.TokenizeHtmlId = (Func)(() => tokenizer.Replace(htmlId, new { Content = content })); + elementShape.TokenizeHtmlClass = (Func)(() => tokenizer.Replace(htmlClass, new { Content = content })); + elementShape.TokenizeHtmlStyle = (Func)(() => tokenizer.Replace(htmlStyle, new { Content = content })); + } + public ElementShapes( ITagBuilderFactory tagBuilderFactory, Work shapeFactory, @@ -32,16 +45,7 @@ namespace Orchard.Layouts.Shapes { public void Discover(ShapeTableBuilder builder) { builder.Describe("Element").OnDisplaying(context => { - var element = (Element)context.Shape.Element; - var content = (ContentItem)context.Shape.ContentItem; - var htmlId = element.HtmlId; - var htmlClass = element.HtmlClass; - var htmlStyle = element.HtmlStyle; - - // Provide tokenizer functions. - context.Shape.TokenizeHtmlId = (Func)(() => _tokenizer.Value.Replace(htmlId, new { Content = content })); - context.Shape.TokenizeHtmlClass = (Func)(() => _tokenizer.Value.Replace(htmlClass, new { Content = content })); - context.Shape.TokenizeHtmlStyle = (Func)(() => _tokenizer.Value.Replace(htmlStyle, new { Content = content })); + AddTokenizers(context.Shape, _tokenizer.Value); }); } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetFieldViewModel.cs b/src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetFieldViewModel.cs new file mode 100644 index 000000000..39a4d8982 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetFieldViewModel.cs @@ -0,0 +1,8 @@ +using Orchard.Layouts.Models; + +namespace Orchard.Layouts.ViewModels { + public class SnippetFieldViewModel { + public SnippetFieldDescriptor Descriptor { get; set; } + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetViewModel.cs b/src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetViewModel.cs new file mode 100644 index 000000000..e8a405dcf --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/ViewModels/SnippetViewModel.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Orchard.Layouts.Models; + +namespace Orchard.Layouts.ViewModels { + public class SnippetViewModel { + public SnippetViewModel() { + FieldEditors = new List(); + } + + public SnippetDescriptor Descriptor { get; set; } + public IList FieldEditors { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.Field.Text.cshtml b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.Field.Text.cshtml new file mode 100644 index 000000000..c67088c4b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.Field.Text.cshtml @@ -0,0 +1,11 @@ +@model Orchard.Layouts.ViewModels.SnippetFieldViewModel +@{ + var field = Model; +} +
+ @Html.Label(field.Descriptor.Name, field.Descriptor.DisplayName.ToString()) + @Html.TextBox(field.Descriptor.Name, field.Value, new { @class = "text large" }) + @if (field.Descriptor.Description != null) { + @Html.Hint(field.Descriptor.Description) + } +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.cshtml b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.cshtml new file mode 100644 index 000000000..ad4028c13 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/Elements.Snippet.cshtml @@ -0,0 +1,10 @@ +@model Orchard.Layouts.ViewModels.SnippetViewModel +@{ + var descriptor = Model; + var fieldEditors = descriptor.FieldEditors; +} +
+ @foreach (var fieldEditor in fieldEditors) { + @Display(fieldEditor) + } +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/Snippet.Design.cshtml b/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/Snippet.Design.cshtml index 914b22b53..27123f005 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/Snippet.Design.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Views/Elements/Snippet.Design.cshtml @@ -1,8 +1,17 @@ @using Orchard.Layouts.Elements +@using Orchard.Layouts.Helpers +@using Orchard.Layouts.Models @{ var element = (Snippet) Model.Element; + var snippetDescriptor = (SnippetDescriptor)Model.SnippetDescriptor; }
- @T("{0} Snippet", element.Descriptor.DisplayText) + @if (snippetDescriptor.Fields.Any()) { +
    + @foreach(var field in snippetDescriptor.Fields) { +
  • @field.DisplayName: @element.Data.Get(field.Name)
  • + } +
+ }
\ No newline at end of file diff --git a/src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml b/src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml new file mode 100644 index 000000000..fc8b7f779 --- /dev/null +++ b/src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml @@ -0,0 +1,10 @@ +@using Orchard.Layouts.Elements +@using Orchard.Layouts.Helpers +@{ + var element = (Snippet)Model.Element; + var tagBuilder = TagBuilderExtensions.CreateElementTagBuilder(Model, "a"); + + tagBuilder.SetInnerText(Html.SnippetField("ButtonText", "Text").WithDisplayName(T("Button Text")).WithDescription(T("The button text label.")).ToString()); + tagBuilder.Attributes["href"] = Html.SnippetField("ButtonUrl", "Text").WithDisplayName(T("Button Url")).WithDescription(T("The button URL.")).ToString(); +} +@tagBuilder.ToHtmlString() \ No newline at end of file diff --git a/src/Orchard.Web/Themes/Themes.csproj b/src/Orchard.Web/Themes/Themes.csproj index 4ca7515ad..615630016 100644 --- a/src/Orchard.Web/Themes/Themes.csproj +++ b/src/Orchard.Web/Themes/Themes.csproj @@ -25,6 +25,7 @@ +
true @@ -160,6 +161,10 @@ Orchard.Framework False + + {6bd8b2fa-f2e3-4ac8-a4c3-2925a653889a} + Orchard.Layouts + @@ -172,6 +177,9 @@ + + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) From e5bb771be106ae5dd5260377f16419959119e768 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 19 Nov 2015 17:56:42 +0100 Subject: [PATCH 2/3] Renamed WithDisplayName to DisplayedAs and removed test view from TheThemeMachine. --- .../Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs | 2 +- .../Themes/TheThemeMachine/Views/ButtonSnippet.cshtml | 10 ---------- src/Orchard.Web/Themes/Themes.csproj | 3 --- 3 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs index f863c0815..af0a18445 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs @@ -36,7 +36,7 @@ namespace Orchard.Layouts.Helpers { return this; } - public SnippetFieldDescriptorBuilder WithDisplayName(LocalizedString value) { + public SnippetFieldDescriptorBuilder DisplayedAs(LocalizedString value) { Descriptor.DisplayName = value; return this; } diff --git a/src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml b/src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml deleted file mode 100644 index fc8b7f779..000000000 --- a/src/Orchard.Web/Themes/TheThemeMachine/Views/ButtonSnippet.cshtml +++ /dev/null @@ -1,10 +0,0 @@ -@using Orchard.Layouts.Elements -@using Orchard.Layouts.Helpers -@{ - var element = (Snippet)Model.Element; - var tagBuilder = TagBuilderExtensions.CreateElementTagBuilder(Model, "a"); - - tagBuilder.SetInnerText(Html.SnippetField("ButtonText", "Text").WithDisplayName(T("Button Text")).WithDescription(T("The button text label.")).ToString()); - tagBuilder.Attributes["href"] = Html.SnippetField("ButtonUrl", "Text").WithDisplayName(T("Button Url")).WithDescription(T("The button URL.")).ToString(); -} -@tagBuilder.ToHtmlString() \ No newline at end of file diff --git a/src/Orchard.Web/Themes/Themes.csproj b/src/Orchard.Web/Themes/Themes.csproj index 615630016..5753cabdd 100644 --- a/src/Orchard.Web/Themes/Themes.csproj +++ b/src/Orchard.Web/Themes/Themes.csproj @@ -177,9 +177,6 @@ - - - 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) From 37550593d42132352f448c8e724bea90b3626791 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 24 Nov 2015 23:19:06 +0100 Subject: [PATCH 3/3] Added support for reusing the same field in a single snippet file. --- .../Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs | 2 +- .../Orchard.Layouts/Providers/SnippetElementHarvester.cs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs index af0a18445..d6b40ab2d 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Helpers/SnippetHtmlExtensions.cs @@ -8,7 +8,7 @@ using Orchard.Localization; namespace Orchard.Layouts.Helpers { public static class SnippetHtmlExtensions { - public static SnippetFieldDescriptorBuilder SnippetField(this HtmlHelper htmlHelper, string name, string type) { + public static SnippetFieldDescriptorBuilder SnippetField(this HtmlHelper htmlHelper, string name, string type = null) { var shape = (dynamic) htmlHelper.ViewData.Model; return new SnippetFieldDescriptorBuilder(shape) diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs index 3db58a023..80808f43b 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Providers/SnippetElementHarvester.cs @@ -141,7 +141,10 @@ namespace Orchard.Layouts.Providers { // Execute the shape and intercept calls to the Html.SnippetField method. var descriptor = new SnippetDescriptor(); shape.DescriptorRegistrationCallback = (Action) (fieldDescriptor => { - descriptor.Fields.Add(fieldDescriptor); + var existingDescriptor = descriptor.Fields.SingleOrDefault(x => x.Name == fieldDescriptor.Name); // Not using Dictionary, as that will break rendering the view for some obscure reason. + + if (existingDescriptor == null) + descriptor.Fields.Add(fieldDescriptor); if (fieldDescriptor.DisplayName == null) fieldDescriptor.DisplayName = new LocalizedString(fieldDescriptor.Name);